It's me again, I'm still getting to limited grips about how PowerShell and SQL work together, this isn't my main field of experience so please excuse the simple mistake I've probably made.
I am trying to update one field in a row. I've searched here and been able to build most of what I need but am getting an error message that states
"Exception calling "ExecuteNonQuery" with "0" argument(s): "Incorrect syntax near 'f7'."
At line:61 char:5
+ $rowsAffected = $command2.ExecuteNonQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException"
This is the code snippet I am using is this section, it is embedded within a foreach loop that steps through the rows of a dataset and sends an email. This section is supposed to change the bit type field "mailed" to true which ensure that only one email is sent per record.
$connect2 = New-Object System.Data.SqlClient.SqlConnection
$connect2.ConnectionString=$ServerConnection
$connect2.Open()
$command2 = New-Object System.Data.SqlClient.SqlCommand
$command2.Connection = $connect2
$MySql2="UPDATE dbo.scans SET Mailed = 'True' WHERE SessionID ="+$BT1
$command2.CommandText = $MySql2
$rowsAffected = $command2.ExecuteNonQuery()
Write-Output "Updating mailed marker"
$connect2.Close()
EBGreen's suggestion worked perfectly. Changing the text string for the $MySql2 = "UPDATE dbo.scans SET Mailed = 'True' WHERE SessionID ='"+$BT1+"'" fixed the error and the field is being updated as required.
Try displaying your sql string to make sure it looks correct. It could be that your $BT1 variable is blank.
write-host $MySql2
Also, when dealing with sql syntax errors it is helpful to log in directly to the sql server and submit the string through the sql command line shell. Once you can submit the string successfully from the command line then check that your powershell string looks exactly the same.
You can make your query string setup more basic. Within PowerShell if you reference a variable with double-quotes, PowerShell will resolve that variable to the set value.
So instead of doing this:
$MySql2="UPDATE dbo.scans SET Mailed = 'True' WHERE SessionID ="+$BT1
Or even this:
$MySql2="UPDATE dbo.scans SET Mailed = 'True' WHERE SessionID ='"+$BT1+"'"
You can simply do this:
$MySql2="UPDATE dbo.scans SET Mailed = 'True' WHERE SessionID ='$BT1'"
Related
What I'm trying here is, to load the data from .xml file to the SQL server database using PowerShell Script.
My Script goes like:
$dataSource = 'dtsrc';
$database = 'tempdb'; #DB
$connection = New-Object System.Data.SqlClient.SqlConnection; #setting connection
$connection.ConnectionString = "Server=$dataSource;Database=$database;Integrated Security=True;";
$connection.Open();
$command = New-Object System.Data.SqlClient.SqlCommand;
$command.Connection = $connection;
$as = New-Object System.Data.SqlClient.SqlDataAdapter;
$as.SelectCommand = $command;
$filename = 'C:\DCT\XML\apc.xml'; #file to be loaded into sql server database table
$ds = New-Object System.Data.DataSet;
$ds.ReadXml($filename); #reading from the file -- line gives output InferSchema
$dt = New-Object System.Data.DataTable;
$dt.Columns.Add("StartTime",[datetime]);
$dt.Columns.Add("EndTime",[datetime]);
$dt.Columns.Add("Status",[int]);
$dt.Columns.Add("ProcessedTime",[datetime]);
$dt.Columns.Add("ScheduleId",[guid]);
$dt.Columns.Add("Model",[string]);
$dt.Columns.Add("ModelVersion",[string]);
$dt.Columns.Add("ModelVersionState",[string]);
$dt.Columns.Add("ModifiedTime",[datetime]);
$dt.Columns.Add("WriteBackLastRunTime",[datetime]);
$dt.Columns.Add("ModifiedBy",[string]);
$dt.Columns.Add("ModelType",[int]);
$dt.Columns.Add("IsTimeRange",[int]);#b
$dt.Columns.Add("WriteBackStatus",[int]);
$dt.Columns.Add("RetryWriteBack",[int]);#b
$dt.Columns.Add("NumOfRetry",[int]);
$dt.Columns.Add("FrequencyUnits",[int]);
$dt.Columns.Add("ScheduleType",[int]);
$dt.Columns.Add("CustomType",[int]);
$dt.Columns.Add("ShiftStartTime",[datetime]);
$dt.Columns.Add("StartWeekDay",[int]);
$dt.Columns.Add("EndWeekDay",[int]);
$dt.Columns.Add("WritebackProcessedTime",[datetime]);
$dt.Columns.Add("DiagStatus",[int]);
$dt.Columns.Add("AccountingPeriodCase_PK_ID",[guid]);
$dt = $ds.Tables[0];
$bcp = New-Object 'Data.SqlClient.SqlBulkCopy' $connection; #bulkcopy to the destination table.
$bcp.DestinationTableName = 'dbo.tempor';
#$bcp.ColumnMappings.Count;
$bcp.ColumnMappings.Clear();
$bcp.ColumnMappings.Add('StartTime','StartTime');
$bcp.ColumnMappings.Add('EndTime','EndTime');
$bcp.ColumnMappings.Add('Status','Status');
$bcp.ColumnMappings.Add('ProcessedTime','ProcessedTime');
$bcp.ColumnMappings.Add('ScheduleId','ScheduleId');
$bcp.ColumnMappings.Add('Model','Model');
$bcp.ColumnMappings.Add('ModelVersion','ModelVersion');
$bcp.ColumnMappings.Add('ModelVersionState','ModelVersionState');
$bcp.ColumnMappings.Add('ModifiedTime','ModifiedTime');
$bcp.ColumnMappings.Add('WriteBackLastRunTime','WriteBackLastRunTime');
$bcp.ColumnMappings.Add('ModifiedBy','ModifiedBy');
$bcp.ColumnMappings.Add('ModelType','ModelType');
$bcp.ColumnMappings.Add('IsTimeRange','IsTimeRange');
$bcp.ColumnMappings.Add('WriteBackStatus','WriteBackStatus');
$bcp.ColumnMappings.Add('RetryWriteBack','RetryWriteBack');
$bcp.ColumnMappings.Add('NumOfRetry','NumOfRetry');
$bcp.ColumnMappings.Add('FrequencyUnits','FrequencyUnits');
$bcp.ColumnMappings.Add('ScheduleType','ScheduleType');
#$bcp.ColumnMappings.Add('CustomType','CustomType');
#$bcp.ColumnMappings.Add('ShiftStartTime','ShiftStartTime');
#$bcp.ColumnMappings.Add('StartWeekDay','StartWeekDay');
#$bcp.ColumnMappings.Add('EndWeekDay','EndWeekDay');
$bcp.ColumnMappings.Add('WritebackProcessedTime','WritebackProcessedTime');
$bcp.ColumnMappings.Add('DiagStatus','DiagStatus');
$bcp.ColumnMappings.Add('AccountingPeriodCase_PK_ID','AccountingPeriodCase_PK_ID');
if ($connection.State -ne [Data.ConnectionState]::Open) {
'Connection to DB is not open.'
Exit
}
$bcp.WriteToServer($dt); #writing to server
$connection.Close();
The error I'm facing is:
Exception calling "WriteToServer" with "1" argument(s): "The given value of type String from the data source cannot be converted to type uniqueidentifier of the specified target column." At C:\Documents\DCT\SavedScripts\XMLtoDB\AccountingPeriodCases\sample.ps1:91 char:1
+ $bcp.WriteToServer($dt); #writing to server
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
and the table I created has the columns with datatypes:
The thing is, I guess i need to convert the String that is in the datatable under the column ScheduleId and AccountingPeriodCase_PK_ID as they are not getting converted to uniqueidentifier.
I tried using
[System.Guid]::Parse($dt.Columns[4]);
[System.Guid]::Parse($dt.Columns[24]);
but the error repeats.
The xml content to be loaded under thr ScheduleId and AccountingPeriodCase_PK_ID looks like:
<ScheduleId>db6f3178-4702-456c-904b-2cd833b54efa</ScheduleId>
<AccountingPeriodCase_PK_ID>9544940d-8d1a-e711-80d3-0050569c2fb6</AccountingPeriodCase_PK_ID>
Could anyone help me resolve this issue?
Thank you
From a scenario, which I had faced earlier, it comes down to the source of your input.
The thing is if you are reading from an XML file, then you are bound to get an error, because while reading from a flat-file(txt, csv) or an XML, PowerShell will resolve the undefined types to String. The trick is to have some sort of control over the source. If your source is a PowerShell variable such as datatable or an array, then you can directly insert values from this variable to your destination table, since the original data types of the columns in a table are preserved.
This is the approach which I followed. In my case, the source was a result of the Invoke-Sqlcmd which preserved the original data types and hence made insertion error less.
Again as mentioned in the comment by OP, he was parsing values based on columns and not rows. This could also lead to an error. For example, there is one more way of inserting values in a table which is using the INSERT statement. Mind you that, the SQL Server INSERT statement inserts value on a row-level and not a column level. In such a scenario, parsing the values column wise may fail.
I've a powershell script connecting to SQL server 2012 database running a SQL query and result set into data table to send formatted email to relevant parties. Below is the code snippet where issue is:
$CBA = New-Object System.Data.DataSet "CBAData"
$sqlConn = New-Object System.Data.SqlClient.SqlConnection("Data Source=DataSource;Initial Catalog=DataCatalog;Integrated Security = False;Connection Timeout=800;User ID = user; Password =pwd;")
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter($CBAData, $sqlConn)
$adapter.Fill($CBA)
I am getting below error running the script:
Exception calling "Fill" with "1" argument(s): "Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
I've tried increasing timeoutin SqlConnection string from initially set up 360 gradually and now upto 800 but still having same issue. Does anyone throw insight into what exactly issue is here? and How can I overome it?
Thank you in advance.
As mentioned by OP - default command execution timeout is 30 seconds. I found below within:
SqlDataAdapter class
that would allow you to increase command execution timeout (insert, update, delete, select command). So in my case below did the trick:
$adapter.SelectCommand.CommandTimeout=60
Hope this helps.
In addition to Zulfiqar's answer, which led me in the right direction. For me, the solution was in the SqlCommand. The error I was getting when setting the property of the adapter was as follows:
The property 'CommandTimeout' cannot be found on this object. Verify that the property exists and can be set.
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
$SqlCmd.CommandTimeout = 60;
I am using a SQL Server job to get some wmiobject details into a table.
This code runs with default installation, but fails when I execute it on a named instance. So far I have seen only one difference in connection, for the named instance, SQL Agent is using with a user name which has "$" as part of the name (i.e. NT Service\SQLAgent$instance)
Is there anyway I can overcome this? Changing the agent account is not an option as most of the servers run with this account and my code needs to work with all accounts.
$conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=$SqlSvr;Initial Catalog=$Database; Integrated Security=SSPI")
$conn.Open()
Executed as user: NT Service\SQLAgent$instance. A job step received
an error at line 21 in a PowerShell script. The corresponding line is
' $conn.Open() '... The error information returned by PowerShell
is: 'Exception calling "Open" with "0" argument(s): "Login failed for
user '(DOMAIN)(COMPUTER)$'." '. Process Exit Code -1.
I tried with "identity impersonate =true" but it didn't accept the command.
Any ideas?
Ether use ' instead of " or use the escape Char ` or use char(36)
"blahblah`$blahblah"
'blahblah$blahblah'
"blahblah$([char](36))blahblah"
I am writing a script in PowerShell to utilize a stored procedure in my SQL Server 2000 database. To utilize the stored procedure w/ params I use the AddWithValue() method for sqlcmd.Parameters. I am attempting to insert a string into a column with data type char of size 8. I have been playing around with the AddWithValue() method, but I keep getting one of the two following errors:
Cannot convert value "aamstest" to type "System.Char". Error: "String must be exactly one character long."
At D:\scripts\SCADAViewBulkAdd\scadaview_bulk_add.ps1:196 char:2
+ $SqlCmd.Paramters.AddWithValue("#USNAME",[char]$USNAME);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastParseTargetInvocation
You cannot call a method on a null-valued expression.
At D:\scripts\SCADAViewBulkAdd\scadaview_bulk_add.ps1:197 char:2
+ $SqlCmd.Paramters.AddWithValue("#GRNAME",$GRNAME);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Stored procedure:
CREATE PROCEDURE spAddUserToGroup
#USNAME char(8), #GRNAME char(8)
AS
BEGIN
INSERT INTO GLOBE_USER_GROUP
VALUES (#USNAME, #GRNAME)
END
GO
AddWithValue() called from here:
# Call SQL Stored Procedure spAddUserToGroup
function SpAddUserToGroup ($usnameParam,$grnameParam)
{
$SqlConnection = New-Object System.DATA.SqlClient.SqlConnection;
$SqlConnection.ConnectionString = "SERVER=server01;DATABASE=FIGDB;UID=y;PWD=y";
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand;
# Indicate working with stored procedure
$SqlCmd.CommandType=[System.Data.CommandType]'StoredProcedure';
# Supply name of stored procedure
$SqlCmd.CommandText = "spAddUserToGroup";
$SqlCmd.Connection = $SqlConnection;
# Set stored procedure parameters
$USNAME = $usnameParam;
$GRNAME = $grnameParam;
Write-Host $USNAME
Write-Host $GRNAME
# Add parameters to string
$SqlCmd.Paramters.AddWithValue("#USNAME",[char]$USNAME);
$SqlCmd.Paramters.AddWithValue("#GRNAME",$GRNAME);
# Initialize SQL Adapter
#$SqlAdapter = New-Object System.Data.SqlClient.SqlAdapter;
#$SqlAdapter.SelectCommand = $SqlCmd;
...
}
Question: how can I utilize the stored procedure to insert a string into a column of type char[8] with PowerShell? Are my errors a result of calling AddWithValue() incorrectly or am I handling my variable types poorly?
New Answer
Turns out you can specify the parameter names, but you don't have to. I think your actual issue here is that you've spelled Parameter wrong, which is why SQL Isn't accepting your input.
Change your code to this, and it should work.
$SqlCmd.Parameters.AddWithValue("#USNAME",[char]$USNAME);
$SqlCmd.Parameters.AddWithValue("#GRNAME",$GRNAME);
Old Answer, Wrong
I don't think you are supposed to specify the parameter name when you call a stored procedure. Try this instead:
Change these two lines:
$SqlCmd.Paramters.AddWithValue("#USNAME",[char]$USNAME);
$SqlCmd.Paramters.AddWithValue("#GRNAME",$GRNAME);
To this:
$SqlCmd.Paramters.AddWithValue([char]$USNAME,$GRNAME)
Also, PowerShell doesn't require line ending characters, like a semicolon.
I'm trying to set a database name in powershell using Microsoft.SqlServer.SMO. When I execute my script it runs in error with the following error text:
format-default : Index was outside the bounds of the array.
+ CategoryInfo : NotSpecified: (:) [format-default], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException,Microsoft.PowerShell.Commands.FormatDefaultCommand
The server is set as follows
$srv = New-Object "Microsoft.SqlServer.Management.SMO.Server" $server
$srv.ConnectionContext.LoginSecure=$false;
$srv.ConnectionContext.set_Login("login");
$srv.ConnectionContext.set_Password("password")
$srv.Databases | Select name,
shows me the proper databases, but when setting the database,
$db = $srv.Databases[$database]
the error is thrown.
This scrip does work in other sqlservers.
Any solutions for this issue?
It looks like the database "CRD_DEV" does not exist on the server where the script throws the error.
That or the user does not have access to that database.
The IndexOutOfRangeException is thrown because there is no item in $srv.Databases that matches "CRD_DEV"