views:

6299

answers:

6

I have a large csv file and I want to execute a stored procedure for each line.

What's the best way to execute a stored procedure from Powershell?

+2  A: 

Consider calling osql.exe (the command line tool for SQL Server) passing as parameter a text file written for each line with the call to the stored procedure.

SQL Server provides some assemblies that could be of use with the name SMO that have seamless integration with PowerShell. Here is an article on that.

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

There are API methods to execute stored procedures that I think are worth being investigated. Here a startup example:

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

smink
+2  A: 

Use sqlcmd instead of osql if it's a 2005 database

Galwegian
This would work (and is a great simple solution) if you have the tools installed on the machine running the script. Otherwise, using .NET's System.Data.SqlClient seems necessary.
Scott Saad
+8  A: 

This answer was pulled from http://www.databasejournal.com/features/mssql/article.php/3683181

This same example can be used for any adhoc queries. Let us execute the stored procedure “sp_helpdb” as shown below.

$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]
Mark Schill
Please remove the line that just says "cmdlets"...that's not a part of the code. Oh, it's you Mark. Yeah, you know better. :D
halr9000
+1  A: 

Here is a function I use to execute sql commands. You just have to change $sqlCommand.CommandText to the name of your sproc and $SqlCommand.CommandType to 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 "Ejecuting SQL => $text..."
Write-Host "Ejecuting SQL => $text..."
$result = $sqlCommand.ExecuteNonQuery()
$sqlConnection.Close()

}

santiiiii
A: 

Here is a function that I use (slightly redacted). It allows input and output parameters. I only have uniqueidentifier and varchar types implemented, but any other types are easy to add. If you use parameterized stored procedures (or just parameterized sql...this code is easily adapted to that), this will make your life a lot easier.

To call the function, you need a connection to the SQL server (say $conn),

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

$res.data #dataset containing the datatables returned by selects $res.outputparams.ID #output parameter ID (uniqueidentifier)

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}
      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",$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}
}
Mike Shepard
A: 

how can i send two parameters to my stored procedure?

this doesnt seem to work:

open database connection

    $conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=SQLSERVER01; Initial Catalog=Igors_Test; Integrated Security=SSPI")
    $cmd = New-Object System.Data.SqlClient.SqlCommand
    $cmd.CommandText = "$sp"
    $cmd.Connection = $conn
    $cmd.CommandTyle=[System.Data.CommandType]'StoredProcedure'

    # need help here....
    $cmd.Parameter.Add(New-Object System.Data.SqlClient.SqlParameter("@Status", SqldbType.VarChar,50)).Value = $Status 
    $cmd.Parameter.Add(New-Object System.Data.SqlClient.SqlParameter("@Message", SqldbType.VarChar,50)).Value = $Message 
    $conn.Open()
    $cmd.ExecuteNonQuery()
Igor