Calling SQL Server stored procedure from powershell - sql-server

I'm trying to call a SQL Server stored procedure from PowerShell but I always get errors on parameters.
Stored procedure has 8 parameters, all with default values
#simchain nvarchar
#idSimulation int
#idCompany varchar
#modelName nvarchar
#simDate datetime
#mySim int
#statusFloor int
#statusCap int
From Management Studio I can call this procedure even without any parameter, so just executing EXEC [dbo].[E_simulations] works.
From PowerShell I create a connection and a command but I always get an error on missing parameters, for example
Procedure or function 'E_simulations' expects parameter '#simchain', which was not supplied.
Here is my test code (just to test proper execution)
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection;
$SqlConnection.ConnectionString = $ConnectionString;
$SqlCommand = $SqlConnection.CreateCommand();
$SqlCommand.CommandText = "EXEC [dbo].[E_simulations]";
$SqlConnection.Open();
$returnedValue = $SqlCommand.ExecuteNonQuery();
Am I missing something?

I have made quick test. I hope this will help
Made test proc:
CREATE PROC doTest (
#param1 INT = 1,
#param2 VARCHAR(10) = 'xxx'
)
AS
BEGIN
PRINT 'THIS ONE'
SELECT 1 As Data
END
Find PowerShell code, which executes proc:
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=localhost;Database=ForTests;Integrated Security=True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = "doTest"
$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]
Execute result gave this
Data
----
1
I done everything same what you wrote and I have result without assigning params

Related

Calling stored procedure with multiple parameters in powershell

I have an stored procedure with many parameters:
CREATE Procedure [dbo].[SQLdatabase]
(
#operation nvarchar(10) = null,
#mode nvarchar(10) = 'smart',
#LogToTable bit = 0
) As .....(it's a long procedure)
And want to call the SProcedure in Powershell code.In the beginning of the code I've called the parameters, if I need to define them in code?
$operation = 'index'
$mode = 'smart'
$LogToTable = $true
Don't know how to complete the below code and call parameters correctly.
$sqlConnection = New-Object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Data Source=$dataSource;Initial Catalog=$database;Integrated Security=False;User ID=$userNameSecret ;Password=$passwordSecret ;Connect Timeout=60;Encrypt=False;TrustServerCertificate=False"
$sqlConnection.Open()
$param =$sqlConnection .Parameters.Add("#operation",[Data.SqlDbType]::nvarchar ,"#mode",[Data.SqlDbType]::nvarchar,"#LogToTable",[Data.SqlDbType]::bit )
Write-Output "DATABASE COMMAND SQLdatabase"
$sqlConnection.ExecuteNonQuery()
$sqlConnection.Close()
I would just use Invoke-SqlCmd for this:
$operation = 'index'
$mode = 'smart'
$LogToTable = $true
$query = #"
exec MyProcedure $operation,$mode,$LogToTable
"#
Invoke-SqlCmd -Query $query -Database $database -ServerInstance $dataSource -Username $userNameSecret -Password $passwordSecret

Calling a stored procedure in PowerShell to insert into SQL Server database

I am attempting to call a stored procedure in a PowerShell script to insert data into a SQL Server table. The script runs fine with no errors, but the information that should be wrote to the table is not there. I'm not sure where the code doesn't work as i am fairly new to PowerShell. Any help with this would be appreciated.
function WriteData
{
param
(
[String] $Server,
[int] $CheckId,
[String] $Investigate
)
try
{
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=MyServer;DataBase=MyDatabase;Integrated Security=SSPI"
$SqlConnection.open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandType = [System.Data.CommandType]::StoredProcedure
$SqlCmd.CommandText = "EXEC dbo.usp_InsertTest"
$param1=$sqlcmd.Parameters.Add("#param1" , [System.Data.SqlDbType]::VarChar)
$param1.Value = $param1
$param2=$sqlcmd.Parameters.Add("#param2" , [System.Data.SqlDbType]::Int)
$param2.Value = $param2
$param3=$sqlcmd.Parameters.Add("#param3" , [System.Data.SqlDbType]::VarChar)
$param3.Value = $param3
$SqlCmd.Connection = $SqlConnection
$tmp=$SqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
}
catch
{
if( $SqlConnection.State -eq "Open" )
{
$SqlConnection.Close()
}
return -1
}
}
WriteData -Param1 Test -Param2 1 -Param3 HelloWorld
This looks wrong:
$param1.Value = $param1
$param2.Value = $param2
$param3.Value = $param3
Try setting those values to what you actually want. For example
$param1.Value = 'hi'
$param2.Value = 1
$param3.Value = 'bye'

PowerShell or SQL Server truncating data

I wrote a script that hits a web page, assigns the HTML to a variable, writes the variable value to the screen (just for my debugging purposes), then submits the data to a SQL stored procedure. The stored procedure variable is varchar(max). The database field is varchar(max). But for some reason, the HTML is truncated everytime. The output to the screen is not, so the problem appears to be with my stored procedure call.
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = 'server=localhost;integrated security=TRUE;database=datawarehouse'
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.CommandType = [System.Data.CommandType]'StoredProcedure'
$sqlCommand.CommandTimeout = 120
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = "insert_html"
$sqlCommand.Parameters.Add("#source", [System.Data.SqlDbType]"VarChar")
$sqlCommand.Parameters["#source"].Value = 'HTML'
$sqlCommand.Parameters.Add("#dataelement", [System.Data.SqlDbType]"VarChar")
$sqlCommand.Parameters["#dataelement"].Value = 'List'
$sqlCommand.Parameters.Add("#data", [System.Data.SqlDbType]"VarChar", -1)
$sqlCommand.Parameters["#data"].Value = $html
$result = $sqlCommand.ExecuteNonQuery()
$sqlConnection.Close()

Automatically save my SQL Server query results

I have a query that compiles some data based on a supplied Id number. I want to run it once for a long list of Ids that I have, and save the result set to a CSV. I know I can do it manually, but I'm looking for an automated way.
I already tried running my query without specifying the Id in the where clause. This ended up giving my a file a little smaller than 1Gb which is too big for needs.
Here is the basic idea of what I am trying to accomplish:
Declare #num int
set #num = 0
While #num < 100
Begin
--I'm trying to figure out a way to store the
--result set generateed by this procedure is saved to 'DataExtract' + #num + '.csv'
Exec LongRunningProcedure #num
Set #num = #num + 1
End
If you have sufficient permissions you could use powershell to accomplish this. I can't really be sure that this will run exactly right for you because I don't know what your output looks like, but hopefully this will get you where you're going.
$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SQLCommand = New-Object system.Data.SqlClient.SqlCommand
$DataSet = New-Object System.Data.DataSet
[STRING]$SQLServer = 'YourServer';
[STRING]$SQLDatabase = 'YourDatabase';
[STRING]$SQLConnectString = "Data Source=$SQLServer; Initial Catalog=$SQLDatabase; Integrated Security=True";
$SQLConnection = New-Object System.Data.SqlClient.SqlConnection($SQLConnectString)
$extractFile = "C:\test.csv"
for($x = 0; $x -le 100; $x++) {
$file = "$($extractFile.Split('.')[0])$($x).csv"
$SQLQuery = "Exec LongRunningProcedure #num = $x"
$SQLConnection.Open()
$SQLCommand.CommandText = $SQLQuery
$SQLCommand.Connection = $SQLConnection
$SQLAdapter.SelectCommand = $SQLCommand
$SqlAdapter.Fill($DataSet) | Out-Null
$SQLConnection.Close()
$DataSet.Tables[0] | Export-Csv $file
}

How do I call a SQL Server stored procedure from PowerShell?

I have a large CSV file and I want to execute a stored procedure for each line.
What is the best way to execute a stored procedure from PowerShell?
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]
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 -storedProcName 'stp_myProc' -parameters #{Param1="Hello";Param2=50} -outparams #{ID="uniqueidentifier"} $conn
retrieve proc output from returned object
$res.data #dataset containing the datatables returned by selects
$res.outputparams.ID #output parameter ID (uniqueidentifier)
The function:
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}
}
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 "Executing SQL => $text..."
Write-Host "Executing SQL => $text..."
$result = $sqlCommand.ExecuteNonQuery()
$sqlConnection.Close()
}
Use sqlcmd instead of osql if it's a 2005 database
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
I include invoke-sqlcmd2.ps1 and write-datatable.ps1 from http://blogs.technet.com/b/heyscriptingguy/archive/2010/11/01/use-powershell-to-collect-server-data-and-write-to-sql.aspx. Calls to run SQL commands take the form: Invoke-sqlcmd2 -ServerInstance "<sql-server>" -Database <DB> -Query "truncate table <table>" An example of writing the contents of DataTable variables to a SQL table looks like: $logs = (get-item SQLSERVER:\sql\<server_path>).ReadErrorLog()
Write-DataTable -ServerInstance "<sql-server>" -Database "<DB>" -TableName "<table>" -Data $logs I find these useful when doing SQL Server database-related PowerShell scripts as the resulting scripts are clean and readable.
Adds CommandType and Parameters to #Santiago Cepas' answer:
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"
I added timeout and show how to reader a scalar or get results using a reader
function exec-query( $storedProcName,$parameters=#{},$conn,$timeout=60){
$cmd=new-object system.Data.SqlClient.SqlCommand
$cmd.CommandType=[System.Data.CommandType]'StoredProcedure'
$cmd.Connection=$conn
$cmd.CommandText=$storedProcName
$cmd.CommandTimeout=$timeout
foreach($p in $parameters.Keys){
[Void] $cmd.Parameters.AddWithValue("#$p",$parameters[$p])
}
#$id=$cmd.ExecuteScalar()
$adapter=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
$dataset=New-Object system.Data.DataSet
$adapter.fill($dataset) | Out-Null
#$reader = $cmd.ExecuteReader()
#$results = #()
#while ($reader.Read())
#{
# write-host "reached" -ForegroundColor Green
#}
return $dataSet.Tables[0]
}

Resources