I am using SQL Server Management Studio version 15.0.18358.0 and I am trying to automate a Flat File SQL Server Imports With PowerShell. I am not an administrator (not sure if that matters). This is my first time attempting such a query as I am completely new to using PowerShell - I referenced the following link which is very useful:
https://www.mssqltips.com/sqlservertip/3208/automating-flat-file-sql-server-imports-with-powershell/.
I basically copy and pasted the code in the link and made edits to the following lines:
$connection.ConnectionString = "Data Source=" + $ENTSQL01LSNR + ";Database=" + $EMTCQIData + ";integrated security=true"
AutoImportCommaFlatFiles -location "Q:\Data Requests\ED TO BED TEST\" -file "ED_TO_BED_DAILY" -extension ".txt" -server "ENTSQL01LSNR" -database "EMTCQIData"
After making these edits, I get the following error:
Exception calling "Open" with "0" argument(s): "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not
accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection
to SQL Server)"
At line:21 char:5
+ $connection.Open()
Full Code
Function AutoImportCommaFlatFiles($location, $file, $extension, $server, $database)
{
$full = $location + $file + $extension
$all = Get-Content $full
$columns = $all[0]
$columns = $columns.Replace(" ","")
$columns = $columns.Replace(",","] VARCHAR(100), [")
$table = "CREATE TABLE " + $file + "([" + $columns + "] VARCHAR(100))"
$connection = New-Object System.Data.SqlClient.SqlConnection
$buildTable = New-Object System.Data.SqlClient.SqlCommand
$insertData = New-Object System.Data.SqlClient.SqlCommand
$connection.ConnectionString = "Data Source=" + $ENTSQL01LSNR + ";Database=" + $EMTCQIData + ";integrated security=true"
$buildTable.CommandText = $table
$buildTable.Connection = $connection
## Added to function
$x = 0
$insertData.CommandText = "EXECUTE stp_CommaBulkInsert #1,#2"
$insertData.Parameters.Add("#1", $full)
$insertData.Parameters.Add("#2", $file)
$insertData.Connection = $connection
$connection.Open()
$buildTable.ExecuteNonQuery()
$connection.Close()
## Added to function
$x = 1
if ($x = 1)
{
$connection.Open()
$insertData.ExecuteNonQuery()
$connection.Close()
}
}
AutoImportCommaFlatFiles -location "Q:\Data Requests\ED TO BED TEST\" -file "ED_TO_BED_DAILY" -extension ".txt" -server "ENTSQL01LSNR" -database "EMTCQIData"
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)
I've tried various Powershell scripts but they fail with:
The following exception occurred while trying to enumerate the collection: "An exception occurred while executing a Transact-SQL statement or batch.".
At H:\Create_SQLAgentJobSripts2.ps1:89 char:22
foreach ($job in $s.JobServer.Jobs)
~~~~~~~~~~~~~~~~~
CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
FullyQualifiedErrorId : ExceptionInGetEnumerator
What has gone wrong or how can I get better debugging on this error?
I executed this script:
.\Create_SQLAgentJobSripts2.ps1 .\ServerNameList.txt
Here's the script
param([String]$ServerListPath)
#write-host "Parameter: $ServerListPath"
#Load the input file into an Object array
$ServerNameList = get-content -path $ServerListPath
#Load the SQL Server SMO Assemly
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
#Create a new SqlConnection object
$objSQLConnection = New-Object System.Data.SqlClient.SqlConnection
#For each server in the array do the following.
foreach($ServerName in $ServerNameList)
{
Write-Host "Beginning with Server: $ServerName"
Try
{
$objSQLConnection.ConnectionString = "Server=$ServerName;Initial Catalog=CED_NCT_RESOURCE_TRACK;Persist Security Info=True;User ID=CEDNCTAdmin;Password=CEDNCTAdmin;"
Write-Host "Trying to connect to SQL Server instance on $ServerName..." -NoNewline
$objSQLConnection.Open() | Out-Null
Write-Host "Success."
$objSQLConnection.Close()
}
Catch
{
Write-Host -BackgroundColor Red -ForegroundColor White "Fail"
$errText = $Error[0].ToString()
if ($errText.Contains("network-related"))
{Write-Host "Connection Error. Check server name, port, firewall."}
Write-Host $errText
continue
}
# Won't be using this object again
Remove-Variable -Name objSQLConnection
#If the output folder does not exist then create it
$OutputFolder = ".\$ServerName"
if (!(Test-Path $OutputFolder))
{
write-host ("Creating directory: " + $OutputFolder)
New-Item -ItemType directory -Path $OutputFolder
}
else
{
write-host ("Directory already exists: " + $OutputFolder)
}
write-host "File: $(".\$OutputFolder\" + $($_.Name -replace '\\', '') + ".job.sql")"
# Connect to the instance using SMO
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') $ServerName
write-host ("SQL Server Edition: " + $s.Edition)
write-host ("SQL Agent ErrorLogFile: " + $s.JobServer.ErrorLogFile)
# Instantiate the Scripter object and set the base properties
$scrp = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($ServerName)
write-host ("SCRP ToString():" + $scrp.ToString())
write-host ("Test scrp - Server: " + $scrp.Server)
#The next step is to set the properties for the script files:
$scrp.Options.ScriptDrops = $False
$scrp.Options.WithDependencies = $False
$scrp.Options.IncludeHeaders = $True
$scrp.Options.AppendToFile = $False
$scrp.Options.ToFileOnly = $True
$scrp.Options.ClusteredIndexes = $True
$scrp.Options.DriAll = $True
$scrp.Options.Indexes = $False
$scrp.Options.Triggers = $False
$scrp.Options.IncludeIfNotExists = $True
#Now, we can cycle through the jobs and create scripts for each job on the server.
# Create the script file for each job
foreach ($job in $s.JobServer.Jobs)
{
$jobname = $job.Name
write-host ("Job: " + $jobname)
$jobfilename = ($OutputFolder + "\" + $jobname + ".job.sql")
$scrp.Options.FileName = $jobfilename
write-host "Filename: $jobfilename"
#This line blows up
$scrp.Script($job)
}
}
Possibly you're not instantiating the Server object correctly. Try the following instead...
# Alternative 1: With servername and port, using Trusted Connection...
$ServerName = 'YourServerName,1433'
$ServerConnection = New-Object Microsoft.SqlServer.Management.Common.ServerConnection -ArgumentList #( $ServerName )
# Alternative 2: With an SqlConnection object
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server=$ServerName;Initial Catalog=CED_NCT_RESOURCE_TRACK;Persist Security Info=True;User ID=CEDNCTAdmin;Password=CEDNCTAdmin;"
$SqlConnection.Open() | Out-Null
$ServerConnection = New-Object Microsoft.SqlServer.Management.Common.ServerConnection -ArgumentList #( $SqlConnection )
# Then...
$Server = New-Object Microsoft.SqlServer.Management.Smo.Server -ArgumentList #( $ServerConnection )
$Server.JobServer.Jobs | ForEach-Object {
Write-Host "Job: $($_.Name)"
}
I have a PowerShell script which runs safely up to the point of an update. I connect to the database and can read from it, however, I have trouble updating.
Here is a copy of the error message I receive:
"Exception calling "ExecuteNonQuery" with "0" argument(s): "There is already an open DataReader associated with this Command which must be closed first."
At C:\xxx\xxx\ToolsController.ps1:37 char:5
+ $InnerCommand.ExecuteNonQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException"
FYI: I posted this before and this is an update to the previous question.
Any help at all would be greatly appreciated.
I have tried attaching the variable at the end of the string i.e '..+$varibale'
also tried #" "# and I have gotten the same result.
$Global:Server = "server"
$Global:Database = "db"
$Global:u = "un"
$Global:p = "pw"
[string]$Query = "SELECT * FROM [dbo].[jobs] WHERE [Run] = 0"
try{
$ConnectionString = "server=$Server;Integrated Security=true;database=$Database;user id=$u;password=$p"
$Connection = New-Object System.Data.SqlClient.SqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
}
catch{
"Failed to connect SQL Server"
}
$Command = $Connection.CreateCommand()
$InnerCommand = $Connection.CreateCommand()
$Command.CommandText = $Query
$jobs = $Command.ExecuteReader()
while ($jobs.Read()){
switch($jobs["Script"]){
15
{
$traverse = $jobs["Frequency"] - 1
While ($traverse -ge 0) {
c:\xx\xx\batch $jobs["Date"]
$traverse--
}
"Updating Database...."
$Query2 = "UPDATE [dbo].jobs SET [Run] = 1 WHERE [ID] = $jobs['ID']" <------Error here.
$InnerCommand.CommandText = $Query2
$InnerCommand.ExecuteNonQuery()
"Updating Completed!"
}
}
}
$Connection.Close()
$Connection.Dispose()
Write-Host "Connection Closed"
Add MultipleActiveResultSets=True to the connection string. This will allow interleaving of UPDATE statements while reading from the data reader.
i am trying to connect to a sql server from powershell and getting this error
Exception calling "Open" with "0" argument(s): "The target principal
name is incorrect. Cannot generate SSPI context." At
C:\Users\Musawwir\Downloads\remotely access db.ps1:10 char:1
+ $Connection.Open()
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: ( [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException Exception calling "Fill" with "1" argument(s):
I can connect to SQL SERVER from other machines through SSMS but can not connect through powershell, also the script runs fine on local machine.
Here is the code i am using :
[string] $Server= "tcp:DESKTOP-J9UQ90E,1433"
[string] $Database = "Eshop"
[string] $SQLQuery= "[dbo].[usp_getCustomerAge]"
$Connection = New-Object System.Data.SQLClient.SQLConnection
$Connection.ConnectionString = "server='$Server';database='$Database';Connection Timeout=300;Integrated Security=TRUE;UID=ali;PWD=1234"
$Connection.Open()
$Command = New-Object System.Data.SQLClient.SQLCommand
$Command.Connection = $Connection
$Command.CommandText = $SQLQuery
$Command.CommandTimeout=500
$adp = New-Object System.Data.SqlClient.SqlDataAdapter $Command
$data = New-Object System.Data.DataSet
$adp.Fill($data) | Out-Null
$data2 = ''
$emp = ''
foreach($Row in $data.Tables.Rows){
[string]$C_name = $Row[0]
$C_name
$data2= $data2+ "|"+$C_name
$C_name = $C_name+"|"
$C_name | out-file "d:\\test4.txt" -Append
}
$Connection.Close()
#$data2 | out-file "d:\\test4.txt"
The user ali wasn't having access to stored procedure .. changed user from ali to sa and integrated security to false solved the problem
$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()