Domanda

Ho un file CSV di grandi dimensioni e desidero eseguire una procedura memorizzata per ogni riga.

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

È stato utile?

Soluzione

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 procedura memorizzata “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]

Altri suggerimenti

Ecco una funzione che utilizzo (leggermente oscurata).Consente parametri di input e output.Ho implementato solo i tipi uniqueidentifier e varchar, ma qualsiasi altro tipo è facile da aggiungere.Se utilizzi procedure memorizzate parametrizzate (o semplicemente SQL parametrizzato... questo codice si adatta facilmente a questo), questo ti renderà la vita molto più semplice.

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

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

recuperare l'output della procedura dall'oggetto restituito

$res.data #dataset contenente i datatable restituiti da selects

$res.outputparams.ID #ID parametro di output (identificatore univoco)

La funzione:

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}
    }

Ecco una funzione che utilizzo per eseguire comandi SQL.Devi solo cambiare $sqlCommand.CommandText con il nome del tuo sproc e $SqlCommand.CommandType con 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()
}

Usa sqlcmd invece di osql se è un database del 2005

Consideriamo la possibilità di chiamare osql.exe (lo strumento da 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 si integrano perfettamente con PowerShell.Ecco un articolo a riguardo.

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

Esistono metodi API per eseguire procedure memorizzate che ritengo valga la pena indagare.Ecco un esempio di avvio:

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

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 assumono 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
Li trovo utili quando si eseguono script PowerShell relativi al database SQL Server poiché gli script risultanti sono puliti e leggibili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top