I'm trying to connect to a Microsoft SQL Database and update any record that the changed field is = to 'x'. I'm able to query the database but when I attempt to do an update I get this error:
Fill : Exception calling "Fill" with "1" argument(s): "Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
This is the script I'm using:
#Create SQL Connection
$con = new-object "System.data.sqlclient.SQLconnection"
#Set Connection String
$con.ConnectionString =(“Data Source=server;Initial Catalog=IDCards;Integrated Security=SSPI”)
$con.open()
$sqlcmd = new-object "System.data.sqlclient.sqlcommand"
$sqlcmd.connection = $con
$sqlcmd.CommandTimeout = 600000
#$sqlcmd.CommandText = “select * from tblPhotoID where changed = 'X'”
$sqlcmd.CommandText = “UPDATE dbo.tblPhotoID SET Changed = '1' WHERE Changed ='X'”
$adapter = New-Object system.data.sqlclient.sqldataadapter ($sqlcmd.CommandText, $con)
$set = New-Object system.data.dataset
$adapter.Fill($set)
There are about 4000 records that would updated currently. The script runs about 30 secs before timing out. I've tried increasing the command timeout and gotten the same results.
Your update statement is not going to return a recordset so there is nothing to fill the dataset. You instead want to try the following:
#Create SQL Connection
$con = new-object "System.data.sqlclient.SQLconnection"
#Set Connection String
$con.ConnectionString =(“Data Source=sb-inft-orange.ads.iu.edu;Initial Catalog=IDCards;Integrated Security=SSPI”)
$con.open()
$sqlcmd = new-object "System.data.sqlclient.sqlcommand"
$sqlcmd.connection = $con
$sqlcmd.CommandTimeout = 600000
$sqlcmd.CommandText = “UPDATE dbo.tblPhotoID SET Changed = '1' WHERE Changed ='X'”
$rowsAffected = $sqlcmd.ExecuteNonQuery()
In your code, you have used $adapter.Fill($set) FYI, It is used to add rows in the DataSet to match those in the data source.Instead you can use $adapter.Update($Set) I think this will solve your problem. Also you can use $sqlcmd.ExecuteNonQuery()
#Create SQL Connection
$con = new-object "System.data.sqlclient.SQLconnection"
#Set Connection String
$con.ConnectionString =(“Data Source=sb-inft-orange.ads.iu.edu;Initial
Catalog=IDCards;Integrated Security=SSPI”)
$con.open()
$sqlcmd = new-object "System.data.sqlclient.sqlcommand"
$sqlcmd.connection = $con
$sqlcmd.CommandTimeout = 600000
$sqlcmd.CommandText = “UPDATE dbo.tblPhotoID SET Changed = '1' WHERE Changed ='X'”
$sqlcmd.ExecuteNonQuery()
$cn = New-Object System.Data.SqlClient.SqlConnection ( "Integrated Security=SSPI;Persist Security Info=False;Initial Catalog.......)
$q = "select ... from .. "
$da = New-Object System.Data.SqlClient.SqlDataAdapter($q, $cn)
$da.SelectCommand.CommandTimeout = 60
Related
This script runs without any problems for a SQL Server connection:
[string] $connectionString = "Server=$server;Database=$database;Integrated Security = False; User ID = $uid; Password = $pwd;"
$sqlConn = New-Object System.Data.SqlClient.SqlConnection
$sqlConn.ConnectionString = $connectionString
$sqlConn.Open()
Write-Host "The connection is $($sqlConn.State)"
$command = $sqlConn.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$sqlConn.Close();
Write-Host "The connection is $($sqlConn.State)"
$table = new-object “System.Data.DataTable”
$table.Load($result)
But only with that result
The connection is Open
The connection is Closed
I have tried many proper SQL queries which run in Management Studio without any problems. Any hint how to properly execute and maybe check the SQL connection?
The $result variable is a SqlDataReader. You need to leave the connection open when loading the data table from the reader:
$sqlConn.Open()
Write-Host "The connection is $($sqlConn.State)"
$command = $sqlConn.CreateCommand()
$command.CommandText = $query
$table = new-object “System.Data.DataTable”
$result = $command.ExecuteReader()
$table.Load($result)
$sqlConn.Close();
Write-Host "The connection is $($sqlConn.State)"
Consider simplifying using a SqlDataAdapter:
$dataAdapter = New-Object System.Data.SqlClient.SqlDataAdapter($query, $connectionString)
$table = new-object “System.Data.DataTable”
$dataAdapter.Fill($table)
If I want to insert the values in the array in one connection, how can i modify the code below? So far i get the error "There is already an open DataReader associated with this Command which must be closed first" unless I put the $Connection.Open() and $Connection.Close() inside the for loop, which will cost me the speed of a single connection.
$list = 'aaa','bbb','cccc','ddddd','eeeee','ffff'
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$Server';database='$Database';trusted_connection=true;"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
foreach($i in $list) {
$sql ="if not exists (select 1 from [bfs] where [key] = '$i' )
begin
insert bfs
select '$i'
end
"
$Command.CommandText = $sql
$Command.ExecuteReader()
}
$Connection.Close()
Try using ExecuteNonQuery() instead of ExecuteReader(). ExecuteNonQuery() does not build a DataReader.
...
$Command.CommandText = $sql
$Command.ExecuteNonQuery()
...
$uncServer = "\\10.243.174.102\e$"
$uncFullPath = "$uncServer\New folder\Demo.txt"
$username = "XYZ"
$password = "xyz"
net use $uncServer $password /USER:$username
$SQLServer = "AP-PUN-SRSTEP29\MSSQLSERVER12" #use Server\Instance for named SQL instances!
$SQLDBName = "SystemDB"
$SqlQuery = "Delete * from V_Solution WHERE Notes ='9.4.4'";
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
#$SqlConnection.open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
I have SQL Server 2012 installed on a remote server and I want to delete a row from a particular table in a specific database, from a local machine using a PowerShell script. Is is possible to do that?
One method is using ADO.NET objects as you would in any .NET application. The PowerShell example below doesn't require SQL tools to be installed.
To execute the query using Windows authentication, specify Integrated Security=SSPI in the connection string:
$connectionString = "Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI";
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString);
$command = New-Object System.Data.SqlClient.SqlCommand("DELETE FROM dbo.YourTable WHERE YourTableID = 1", $connection);
$connection.Open();
$rowsDeleted = $command.ExecuteNonQuery();
Write-Host "$rowsDeleted rows deleted";
$connection.Close();
To execute the query using SQL authentication, specify User ID=YourSqlLogin;Password=YourSqlLoginPassword in the connection string.
$connectionString = "Data Source=YourServer;Initial Catalog=YourDatabase;User ID=YourSqlLogin;Password=YourSqlLoginPassword";
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString);
$command = New-Object System.Data.SqlClient.SqlCommand("DELETE FROM dbo.YourTable WHERE YourTableID = 1", $connection);
$connection.Open();
$rowsDeleted = $command.ExecuteNonQuery();
Write-Host "$rowsDeleted rows deleted";
$connection.Close();
In either case, DELETE permissions on the table are required.
I'm not sure of the purpose of the NET USE command in the script you added to your question, unless that is to authenticate to the server in a workgroup environment. Personally, I would just use SQL authentication and remove the NET USE ugliness.
EDIT:
In the case of multiple SELECT statements in the same batch, each will return a separate recordset. This will require invoking NextRecordset if you are using a DataReader, which will return false when no more recordsets are available:
$reader = $command.ExecuteReader();
do {
While($reader.Read()) {
#process row here;
}
} while($reader.NextResult());
Alternatively, you could use a DataAdapter to fill a 'DataSet'. The DataSet will contain a separate DataTable for each resultset:
$da = New-Object System.Data.SqlClient.SqlDataAdapter($command);
$ds = New-Object System.Data.DataSet;
$null = $da.Fill($ds);
foreach($dt in $ds.Tables) {
$dt | Out-GridView;
}
You could also tweak your SQL query to concatenate the results into a single resultset using UNION ALL if the number of columns and data types are identical. Here's an example snippet:
$sqlQuery = #("
SELECT *
FROM DB926.dbo.Version_Solution
WHERE Notes ='9.2.7'
UNION ALL
SELECT *
FROM DB_926.dbo.Version_Solution
WHERE Notes ='9.2.7'";
);
$command = New-Object System.Data.SqlClient.SqlCommand($sqlQuery, $connection);
Change your code like this :
$uncServer = "\\10.243.174.102\e$"
$uncFullPath = "$uncServer\New folder\Demo.txt"
$username = "XYZ"
$password = "xyz"
net use $uncServer $password /USER:$username
$SQLServer = "AP-PUN-SRSTEP29\MSSQLSERVER12" #use Server\Instance for named SQL instances!
$SQLDBName = "SystemDB"
$SqlQuery = "Delete from V_Solution WHERE Notes ='9.4.4'";
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlConnection.open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlCmd.ExecuteNonQuery
$SqlConnection.Close()
I have a Powershell Function that is being used to run multiple queries in SQL and export as CSVs. Each of these queries relies on a date variable. Is there a way to pass this date variable from Powershell into these SQL Scripts (not stored procedures) using my current setup? Any help is much appreciated!
Function Run-Query
{
param([string[]]$queries,[string[]]$sheetnames)
Begin
{
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $Database; User ID = $uid; Password = $pwd;"
Write-host "Connection to database successful."
}#End Begin
Process
{
# Loop through each query
For($i = 0; $i -lt $queries.count; $i++)
{
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
# Use the current index ($i) to get the query
$SqlCmd.CommandText = $queries[$i]
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
# Use the current index ($i) to get the sheetname for the CSV
$DataSet.Tables[0] #| Export-Csv -NoTypeInformation -Path "C:\Users\mbaron\Downloads\$($sheetnames[$i]).csv"
}
}#End Process
End
{
$SqlConnection.Close()
}
}#End function run-query.
You could add a marker in your queries where the data is being used, then do a replace with the relevant date, e.g.:
cls
$date = '1/1/2016'
$query = 'some $$marker$$ script'
$query = $query.replace('$$marker$$', $date )
$query
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()