it-swarm.it

Come si chiama una procedura memorizzata di SQL Server da PowerShell?

Ho un grande file CSV e voglio eseguire una stored procedure per ogni riga.

Qual è il modo migliore per eseguire una procedura memorizzata da PowerShell?

37
Andrew Jones

Questa risposta è stata estratta da http://www.databasejournal.com/features/mssql/article.php/3683181

Questo stesso esempio può essere utilizzato per qualsiasi query ad hoc. Eseguiamo la stored procedure "sp_helpdb" come mostrato di seguito.

$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]
57
Mark Schill

Ecco una funzione che uso (leggermente redatta). Consente i parametri di input e output. Ho implementato solo i tipi uniqueidentifier e varchar, ma altri tipi sono facili da aggiungere. Se si usano procedure memorizzate parametrizzate (o semplicemente sql parametrizzati ... questo codice si adatta facilmente a questo), questo renderà la vita molto più facile.

Per chiamare la funzione, è necessaria una connessione al server SQL (ad esempio $ conn), 

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

recupera l'output proc dall'oggetto restituito

$ res.data #dataset contenente i dati restituiti da select

$ res.outputparams.ID #output ID parametro (uniqueidentifier)

La funzione:

function exec-storedprocedure($storedProcName,  
        [hashtable] [email protected]{},
        [hashtable] [email protected]{},
        $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}
    }
8
Mike Shepard

Ecco una funzione che uso per eseguire i comandi sql. Devi solo modificare $ sqlCommand.CommandText con il nome del tuo sproc e $ SqlCommand.CommandType su 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()
}
6
Santiago Cepas

Usa sqlcmd invece di osql se è un database del 2005

3
Galwegian

Si consiglia di chiamare osql.exe (lo strumento della riga di comando per SQL Server) passando come parametro un file di testo scritto per ogni riga con la chiamata alla stored procedure.

SQL Server fornisce alcuni assembly che potrebbero essere utili con il nome SMO che hanno una perfetta integrazione con PowerShell. Ecco un articolo su questo.

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

Esistono metodi API per eseguire stored procedure che penso valga la pena di essere investigate. Ecco un esempio di avvio:

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

2
Jorge Ferreira

Includo invoke-sqlcmd2.ps1 e write-datatable.ps1 da http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql. aspx . Le chiamate per eseguire comandi SQL hanno la forma: 
Invoke-sqlcmd2 -ServerInstance "<sql-server>" -Database <DB> -Query "truncate table <table>" 
Un esempio di scrittura del contenuto delle variabili DataTable su una tabella SQL è simile a: 
$logs = (get-item SQLSERVER:\sql\<server_path>).ReadErrorLog() Write-DataTable -ServerInstance "<sql-server>" -Database "<DB>" -TableName "<table>" -Data $logs
Trovo questi utili quando si eseguono script PowerShell relativi al database di SQL Server poiché gli script risultanti sono puliti e leggibili.

0
Ken