SQL Query through powershell w/variables - sql

I am attempting to run a query against SQL using powershell and was successful until I attempted to throw parameters in the mix. My code is as follows:
$parameter="TEST"
$connectionString = "CONNECTION STRING";
$Connection = New-Object System.Data.OleDb.OleDbConnection $connectionString;
$Values = New-Object System.Data.DataSet;
$SelectCommand = "Select Value FROM dbo.Values WHERE Value=#param";
$Command = New-Object System.Data.OleDb.OleDbCommand $SelectCommand,$Connection;
$Command.Parameters.Add("#param", [System.Data.OleDb.OleDbType]::VarChar, 50)
$Command.Parameters["#param"].Value = $parameter;
$adapter = New-Object System.Data.OleDb.OleDbDataAdapter $Command;
[void] $adapter.Fill($Values);
foreach($a in $Values.tables[0].Rows )
{
#handle returned values
}
I have messed around with different ways of passing a parameter that i have found online and always get the same result:
Exception calling "Fill" with "1" argument(s): "Must declare the scalar variable "#try"."
At line:28 char:31
+ [void] $adapter.Fill <<<< ($Values);
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Any help would be appreciated, finding good examples of powershell SQL queries has been rough. Using OLeDB is not necessary, if someone has an example using another provider that is fine as well, I have also been messing with System.Data.SqlClient.SqlConnection without success.

Since you are using OleDbCommand your parameter markers should be ? instead of #paramname.
Or you can use System.Data.SqlClient.SqlCommand instead of OleDbCommand so you can use #paramname.
Check this out:
http://blogs.msdn.com/b/spike/archive/2010/03/03/must-declare-the-scalar-variable.aspx

Related

is there a way to capture a exact error message in ps catch block?

is there any way to capture specific error message while this call to store that error message in sql table ?
function Get-SqlData {
param([string]$serverName=$(throw 'serverName is required.'), [string]$databaseName=$(throw 'databaseName is required.'),
[string]$query=$(throw 'query is required.'))
try {
Write-Verbose "Get-SqlData serverName:$serverName databaseName:$databaseName query:$query"
$connection = new-object system.data.sqlclient.sqlconnection( "Data Source=$serverName;Initial Catalog=$databaseName;Integrated Security=SSPI;")
$adapter = new-object system.data.sqlclient.sqldataadapter ($query, $connection)
$table = new-object system.data.datatable
[void]$adapter.Fill($table) #| out-null
$table
} catch {
write-host $Server
write-host 'Connection issue'
}
}
$Query = "set nocount on; SELECT CASE WHEN Is_Clustered = 1 THEN SQLClusterName ELSE ServerName END FROM Server_Master_List WHERE Is_Monitored = 1 "
$Servers = sqlcmd -b -S XYZ-XYZ -d DBA -h -1 -Q $Query -W
$sqltbl = #()
foreach($Server in $Servers) { $sqltbl += Get-SqlData $Server 'master' $qry }
#$sqltbl
<#Insert data from Powershell variable to SQL table #>
$connectionString = "Server=$env:ComputerName;Database=DBA;Integrated Security=SSPI;"
Yes. You can tell PowerShell to only catch certain types of exceptions.
For example...
$serverName = 'SOMERANDOMSERVER'
$databaseName = 'DoesntMatter'
$query = 'SELECT 1'
try {
$connection = New-Object System.Data.SqlClient.SqlConnection ("Data Source=$serverName;Initial Catalog=$databaseName;Integrated Security=SSPI;")
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter ($query, $connection)
$table = New-Object System.Data.DataTable
[void]$adapter.Fill($table)
$table
} catch [System.Data.SqlClient.SqlException] {
'CAUGHT A SQL EXCEPTION!!'
} catch {
'Caught some other type of exception'
}
However, if you want to get further into the details, you'll need to start parsing the exceptions themselves.
And that's where this leads me to ask...why do you need to do this? A query with bad syntax, a query that throws an error, an unavailable server...those will all return a SqlException. Do you plan on implementing something which handles each of these exceptions in a particular way?
Personal opinion:
Any time I see someone starting to write code in PowerShell for running SQL queries, my first question is...Are you trying to build some sort of maintenance/utility script where it's okay to utilize existing community modules? If so, you need to look up dbatools. It's a PowerShell module that is packed with cmdlets that handle all this stuff for you. For example, you've basically just written their cmdlet called Invoke-DbaQuery
Another tip...learn about advanced parameters in PowerShell. You can add various checks against parameters to ensure they are mandatory, and even include verification checks to ensure the parameter values are valid prior to executing the script. That would allow you to properly implement required parameters, and you can remove the hack you've used here.

SQL DB Power Shell Connection Code error I don't understand

So I have a peice of code that I'm using to try to write to the database but I keep getting an error at the bottom that makes no sense. everything seems to work interdependantly but executing the code is just... no.
I pulled this db query ps code from
https://blogs.msdn.microsoft.com/buckwoody/2009/04/13/run-a-sql-server-command-from-powershell-without-the-sql-server-provider/
here is the code, the error is below the Close().
I'm totally lose. Help?
$strserver = "1sl-den-db03"
$strdatabase = "reporting"
$strusername = "belamiinc\PSscripts"
#you can get convert pass by "p#ssw0rdt3xt" | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File "C:\Users\daniel.williams\Documents\Scriptcred.txt"
$strpassword = Get-Content "C:\Users\daniel.williams\Documents\Scriptcred.txt" | ConvertTo-SecureString
#$strQuery = "
#INSERT INTO EventLog (SourceID, Started, Completed, Result, Context, Machine)
#SELECT (50, null, null, 'error undefined query','query run outside of manufacturer','1sl-den-db03')
#"
$strQuery = "
insert into [reporting].[dbo].[password] (Username, Password)
select (test, testpw)
"
# Create and open a database connection
$sqlConnection = new-object System.Data.SqlClient.SqlConnection "server=$strserver;database=$strdatabase;Integrated Security=SSPI; User ID=$strusername; password=$strpassword"
#Create a command object
$sqlCommand = $sqlConnection.CreateCommand()
$sqlCommand.CommandText = $strQuery
$sqlConnection.Open()
#Execute the Command
$sqlCommand.ExecuteNonQuery()
$sqlConnection.Close()
The error is:
PS C:\Windows> Y:\DEPT - IT\Scripting\PSConnecttoSQL.ps1
Exception calling "ExecuteNonQuery" with "0" argument(s): "Incorrect syntax near ','."
At Y:\DEPT - IT\Scripting\PSConnecttoSQL.ps1:27 char:1
+ $sqlCommand.ExecuteNonQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException
You don't need a reader for an INSERT command. Change this line:
$sqlReader = $sqlCommand.ExecuteReader()
Into:
$sqlCommand.ExecuteNonQuery()
More about SqlCommand.ExecuteNonQuery()

Powershell Stored Procedure Parameters not being sent

I have a stored procedure in a PowerShell (version 4) script that logs the results of a job
function Log-Build($lastExitCode, $result, $taskId) {
$date = Get-Date
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$cmd = New-Object System.Data.SqlClient.SqlCommand
$myResult = $result -join "<br/>`r`n" |Out-String
$cmd.Connection = $connection;
$cmd.CommandText = "LSBuild_LogAndMailResult";
$cmd.Parameters.AddWithValue("#Task_ID",[string]$taskId);
$cmd.Parameters.AddWithValue("#Result",[string]$myResult);
$cmd.Parameters.AddWithValue("#Deployment_Status",[int]$lastExitCode);
$connection.Open()
$cmd.ExecuteNonQuery() | Out-Null
$connection.Close()
}
However, when I run it, I always get the following error response:
Exception calling "ExecuteNonQuery" with "0" argument(s): "Procedure or function 'LSBuild_LogAndMailResult' expects parameter '#Deployment_Status',
which was not supplied.
I checked in the terminal window in Powershell ISE to make sure the parameter was there ( $cmd.Parameters["#Deployment_Status"].value;) and it is definitely being added. Not sure why it's not getting passed to the database
You must set command type as stored procedure
$cmd.CommandType = [System.Data.CommandType]::StoredProcedure

Re-run SQL on error

I am building a PowerShell script to clean up the hundreds of batch file executions and scheduled tasks that I have running on my machine.
One of the processes that I am cleaning up is a connection to a remote SQL server that downloads .csv files onto a network location.
It works over and over again and then I receive the following message
Exception calling "Fill" with "1" argument(s): "ExecuteReader: CommandText
property has not been initialized"
At L:\Operations Database\BatchScriptExecutions\PS\Scripts\0000 - 0100\ControlsBrokerRec.ps1:2426 char:1
+ $SqlAdapter.Fill($DataSet);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
I am wondering what I can do to re-run the process if this error occurs? Is there a way in PowerShell to loop on error?
The code that is running is multiple iterations of the following:
## - Runs Script from Set Location
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
$SqlCmd.CommandTimeout=$timeout;
$SqlCMD.CommandText = $CL3CASHPOSITIONSSCRIPTWINS;
$SqlCmd.Connection = $SqlConnection;
## - Extract Data and build sql data object
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter;
$SqlAdapter.SelectCommand = $SqlCmd;
$DataSet = New-Object System.Data.DataSet;
$SqlAdapter.Fill($DataSet);
$DataSetTable = $DataSet.Tables["Table"];
## - Check for Null Return of Data into table
if ($DataSet.Tables["Table"]) {
$isnotnull
$DataSet.Tables["Table"] | Export-Csv $CL3CASHPOSITIONSEXPORTWINS -NoTypeInformation
echo "Cash Wins"
} else {
echo "NULL NULL NULL"
}
The issue happens so sporadically that I am unsure how I can test solutions for this. I am assuming that there should be some kind of catch statement within the code, but I'm at a loss.

Data from Powershell forms with blank fields into SQL Server database

So far I have created a form in Powershell studio and from that form I want to take the user's input and place it into a SQL Server database.
For the most part this works fine, unless a textfield in the form is left blank, then an error occurs. I need to be able to insert the data even if some of the fields are not complete as people are able to go back and edit and add to that data and then update it in the database.
This is the error I get if I leave a textbox blank:
ERROR: Exception calling "Fill" with "1" argument(s): "Incorrect syntax near ','." testTabForm.psf (59): ERROR: At Line: 59 char: 3
ERROR: + $SqlAdapter.Fill($DataSet)
ERROR: + ~~~~~~~~~~~~~~~~~~~~~~~~~~
ERROR: + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
ERROR: + FullyQualifiedErrorId : SqlException
And the code which does this aspect of it is the following:
$server = "server"
$database = "database"
$A = $record.Text
$B = $textB.Text
$C = $textC.Text
$insert = "INSERT INTO dbo.AMY (ColumnA, ColumnB, ColumnC) VALUES ($A,$B,$C)"
$connectionTemplate = "Data Source=$server;Integrated Security=SSPI;Initial Catalog=$database;"
$connectionString = [string]::Format($connectionTemplate, $server, $database)
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$command = New-Object System.Data.SqlClient.SqlCommand
$command.CommandText = $insert
$command.Connection = $connection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $command
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$connection.Close()
Any ideas on how to fix this would be appreciated.
Test for the existance of B and C building your insert command along the way.$insert = "INSERT INTO dbo.AMY (ColumnA, ColumnB, ColumnC) VALUES ($A, "
if ($B.Length) { $insert += "'$B', " }
else { $insert += "NULL, " }
if ($C.Length) { $insert += "'$C')" }
else { $insert += "NULL)" }
The problem ended up being a simple syntax error, the variables needed to be in quotes for a string specifically single quotes, once I did this it worked perfectly. Thanks.