【问题标题】:How do I call a SQL Server stored procedure from PowerShell?如何从 PowerShell 调用 SQL Server 存储过程?
【发布时间】:2008-09-17 13:48:25
【问题描述】:

我有一个大的 CSV 文件,我想为每一行执行一个存储过程。

从 PowerShell 执行存储过程的最佳方式是什么?

【问题讨论】:

    标签: sql-server powershell


    【解决方案1】:

    这个答案来自http://www.databasejournal.com/features/mssql/article.php/3683181

    同样的例子可以用于任何即席查询。让我们执行如下所示的存储过程“sp_helpdb”。

    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Server=HOME\SQLEXPRESS;Database=master;Integrated Security=True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = "sp_helpdb"
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $SqlConnection.Close()
    $DataSet.Tables[0]
    

    【讨论】:

    • 注意:如果你调用的是一个有参数的存储过程,你还应该设置命令类型:$sqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure
    • 添加参数:$SqlCmd.Parameters.AddWithValue("@paramName", "$param") | Out-Null.
    【解决方案2】:

    这是我使用的一个函数(略有删节)。它允许输入和输出参数。我只实现了 uniqueidentifier 和 varchar 类型,但任何其他类型都很容易添加。如果你使用参数化的存储过程(或者只是参数化的 sql...这个代码很容易适应那个),这会让你的生活变得更轻松。

    要调用该函数,您需要连接到 SQL 服务器(比如 $conn),

    $res=exec-storedprocedure -storedProcName 'stp_myProc' -parameters @{Param1="Hello";Param2=50} -outparams @{ID="uniqueidentifier"} $conn

    从返回的对象中检索 proc 输出

    $res.data #dataset 包含 selects 返回的数据表

    $res.outputparams.ID #输出参数ID(唯一标识符)

    功能:

    function exec-storedprocedure($storedProcName,  
            [hashtable] $parameters=@{},
            [hashtable] $outparams=@{},
            $conn,[switch]$help){ 
    
            function put-outputparameters($cmd, $outparams){
                foreach($outp in $outparams.Keys){
                    $cmd.Parameters.Add("@$outp", (get-paramtype $outparams[$outp])).Direction=[System.Data.ParameterDirection]::Output
                }
            }
            function get-outputparameters($cmd,$outparams){
                foreach($p in $cmd.Parameters){
                    if ($p.Direction -eq [System.Data.ParameterDirection]::Output){
                    $outparams[$p.ParameterName.Replace("@","")]=$p.Value
                    }
                }
            }
    
            function get-paramtype($typename,[switch]$help){
                switch ($typename){
                    'uniqueidentifier' {[System.Data.SqlDbType]::UniqueIdentifier}
                    'int' {[System.Data.SqlDbType]::Int}
                    'xml' {[System.Data.SqlDbType]::Xml}
                    'nvarchar' {[System.Data.SqlDbType]::NVarchar}
                    default {[System.Data.SqlDbType]::Varchar}
                }
            }
            if ($help){
                $msg = @"
        Execute a sql statement.  Parameters are allowed.  
        Input parameters should be a dictionary of parameter names and values.
        Output parameters should be a dictionary of parameter names and types.
        Return value will usually be a list of datarows. 
    
        Usage: exec-query sql [inputparameters] [outputparameters] [conn] [-help]
        "@
                Write-Host $msg
                return
            }
            $close=($conn.State -eq [System.Data.ConnectionState]'Closed')
            if ($close) {
               $conn.Open()
            }
    
            $cmd=new-object system.Data.SqlClient.SqlCommand($sql,$conn)
            $cmd.CommandType=[System.Data.CommandType]'StoredProcedure'
            $cmd.CommandText=$storedProcName
            foreach($p in $parameters.Keys){
                $cmd.Parameters.AddWithValue("@$p",[string]$parameters[$p]).Direction=
                      [System.Data.ParameterDirection]::Input
            }
    
            put-outputparameters $cmd $outparams
            $ds=New-Object system.Data.DataSet
            $da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
            [Void]$da.fill($ds)
            if ($close) {
               $conn.Close()
            }
            get-outputparameters $cmd $outparams
    
            return @{data=$ds;outputparams=$outparams}
        }
    

    【讨论】:

    • 在 NVARCHAR 输出变量上,您必须指定 Size 属性,因此如上所示的代码将导致错误。
    【解决方案3】:

    这是我用来执行 sql 命令的函数。您只需将 $sqlCommand.CommandText 更改为存储过程的名称,将 $SqlCommand.CommandType 更改为 CommandType.StoredProcedure。

    function execute-Sql{
        param($server, $db, $sql )
        $sqlConnection = new-object System.Data.SqlClient.SqlConnection
        $sqlConnection.ConnectionString = 'server=' + $server + ';integrated security=TRUE;database=' + $db 
        $sqlConnection.Open()
        $sqlCommand = new-object System.Data.SqlClient.SqlCommand
        $sqlCommand.CommandTimeout = 120
        $sqlCommand.Connection = $sqlConnection
        $sqlCommand.CommandText= $sql
        $text = $sql.Substring(0, 50)
        Write-Progress -Activity "Executing SQL" -Status "Executing SQL => $text..."
        Write-Host "Executing SQL => $text..."
        $result = $sqlCommand.ExecuteNonQuery()
        $sqlConnection.Close()
    }
    

    【讨论】:

    • $sqlCommand.Dispose()$sqlConnection.Dispose() 怎么样
    【解决方案4】:

    如果是 2005 数据库,则使用 sqlcmd 而不是 osql

    【讨论】:

    • 如果您在运行脚本的机器上安装了工具,这将起作用(并且是一个非常简单的解决方案)。否则,使用 .NET 的 System.Data.SqlClient 似乎是必要的。
    【解决方案5】:

    考虑调用 osql.exe(SQL Server 的命令行工具)作为参数传递为每一行编写的文本文件,并调用存储过程。

    SQL Server 提供了一些与 PowerShell 无缝集成的名为 SMO 的程序集。这是一篇关于此的文章。

    http://www.databasejournal.com/features/mssql/article.php/3696731

    有一些 API 方法可以执行存储过程,我认为这些方法值得研究。这里是一个启动示例:

    http://www.eggheadcafe.com/software/aspnet/29974894/smo-running-a-stored-pro.aspx

    【讨论】:

      【解决方案6】:

      我包括来自http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql.aspxinvoke-sqlcmd2.ps1write-datatable.ps1。运行 SQL 命令的调用采用以下形式:
      Invoke-sqlcmd2 -ServerInstance "<sql-server>" -Database <DB> -Query "truncate table <table>"
      将 DataTable 变量的内容写入 SQL 表的示例如下:
      $logs = (get-item SQLSERVER:\sql\<server_path>).ReadErrorLog() Write-DataTable -ServerInstance "<sql-server>" -Database "<DB>" -TableName "<table>" -Data $logs
      我发现这些在执行 SQL 时很有用与服务器数据库相关的 PowerShell 脚本,因为生成的脚本干净且可读。

      【讨论】:

        【解决方案7】:

        CommandTypeParameters 添加到@Santiago Cepas 的回答中:

        function Execute-Stored-Procedure
        {
            param($server, $db, $spname)
            $sqlConnection = new-object System.Data.SqlClient.SqlConnection
            $sqlConnection.ConnectionString = 'server=' + $server + ';integrated security=TRUE;database=' + $db 
            $sqlConnection.Open()
            $sqlCommand = new-object System.Data.SqlClient.SqlCommand
            $sqlCommand.CommandTimeout = 120
            $sqlCommand.Connection = $sqlConnection
            $sqlCommand.CommandType= [System.Data.CommandType]::StoredProcedure
            # If you have paramters, add them like this:
            # $sqlCommand.Parameters.AddWithValue("@paramName", "$param") | Out-Null
            $sqlCommand.CommandText= $spname
            $text = $spname.Substring(0, 50)
            Write-Progress -Activity "Executing Stored Procedure" -Status "Executing SQL => $text..."
            Write-Host "Executing Stored Procedure => $text..."
            $result = $sqlCommand.ExecuteNonQuery()
            $sqlConnection.Close()
        }
        
        
        # Call like this:
        Execute-Stored-Procedure -server "enter-server-name-here" -db "enter-db-name-here" -spname "enter-sp-name-here"
        

        【讨论】:

          猜你喜欢
          • 2015-05-08
          • 1970-01-01
          • 1970-01-01
          • 2014-03-30
          • 2021-05-26
          • 2012-02-10
          • 1970-01-01
          • 2020-07-09
          • 2013-08-31
          相关资源
          最近更新 更多