SQL Server Update Statement via Powershell - sql-server

I am currently using the following piece of code of testing purposes.
$database = 'REMOVED'
$server = 'REMOVED'
$SQLServer = "REMOVED"
$SQLDBName = "REMOVED"
$SQLuser = "REMOVED"
$SQLpassword = "REMOVED"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database =
$SQLDBName; User ID = $SQLuser; Password = $SQLpassword;"
$SqlConnection.Open()
$update = #"
update ca_contact set last_name='Rech' where userid='OR010101'
"#
$dbwrite = $SqlConnection.CreateCommand()
$dbwrite.CommandText = $update
$dbwrite.ExecuteNonQuery()
$Sqlconnection.Close()
I am getting a return value of '1' which tells me that the statement appears to be working. But the value never gets written to the database when viewing via SQL Server Management Studio.

It must be how you are building the connection string.. I am unsure.. but this should work.
$SQLServer = "tcp:ServerName.Domain.com"
$SQLDB = 'DB_name'
$Password = "VeryComplexPassword"
$USer = "Sophisticated_User"
$cn = new-object system.data.SqlClient.SqlConnection("Server=$SQLServer;Database=$SQLDB;User Id=$User;Password=$Password;");
$ds = new-object "System.Data.DataSet" "DataObject"
$q =
#"
UPDATE [DB_Name].[schema].[Table_Name]
SET Updated_Column = 'New_Value'
WHERE Filter_Column = 'Filter_Criteria'
"#
$da = new-object "System.Data.SqlClient.SqlDataAdapter" ($q, $cn)
$da.Fill($ds)

Related

Copy SQL Server database using PowerShell script in mixed mode

I would like to create a SQL Server database using a PowerShell script using username and password. I have used this script:
$SQLInstanceName = "(localdb)\MSSQLLocalDB"
$Server = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArgumentList $SQLInstanceName
# This sets the connection to mixed-mode authentication
$Server.ConnectionContext.LoginSecure=$false;
# This sets the login name
$Server.ConnectionContext.set_Login("test");
# This sets the password
$Server.ConnectionContext.set_Password("*******")
$SourceDBName = "##SourceDBName##"
$SourceDB = $Server.Databases[$SourceDBName]
$CopyDBName = "##DestDBName##"
$CopyDB = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Database -ArgumentList $Server , $CopyDBName
$CopyDB.Create()
$ObjTransfer = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Transfer -ArgumentList $SourceDB
$ObjTransfer.CopyAllTables = $true
$ObjTransfer.Options.WithDependencies = $true
$ObjTransfer.Options.ContinueScriptingOnError = $true
$ObjTransfer.DestinationDatabase = $CopyDBName
$ObjTransfer.DestinationServer = $Server.Name
$ObjTransfer.DestinationLoginSecure = $true
$ObjTransfer.CopySchema = $true
$ObjTransfer.ScriptTransfer() enter code here
$ObjTransfer.TransferData()
But I get this error:
SetParent failed for Database 'coupadb_master_TestClient'. "
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)

Powershell throws error Cannot perform operation because operation ReportWrongProviderType is not valid

I have a powershell script that, when I run it from the powershell command line, it works fine. However, when I run it via a SQL Server Agent Job it throws this error:
A job step received an error at line 149 in a Powershell script. The
corresponding line is 'if ($Datatable.Rows.Count > 0)' Correct the
script and reschedule the job. The error information returned by
PowerShell is 'Cannot perform operation because operation
"ReportWrongProviderType" is not valid. Remove operation
"ReportWrongProviderType", or investigate why it is not valid.'
Process Exit Code -1.
Powershell script throwing the error:
function Get-BackupHistory
{
#module to gather all of the backup history data for the DBAdmin_Central database
Write-Host "Get Backup History"
#query to get list of servers to run queries against - primary oltp's
#this will run against the central management server
$ServerQuery =
"
select
ss.PK_ServerID as id,
ss.ServerName as name,
isnull(bms.MaxMediaSetID, 0) as MaxMediaSetID,
isnull(MaxBackupSetID, 0) as MaxBackupSetID
from DBAdmin_Central.CentMang.SQLServers ss
left outer join
(
select
FK_ServerID,
max(media_set_id) as MaxMediaSetID
from DBAdmin_Central.CentMang.backupmediaset
group by FK_ServerID
) bms
on ss.PK_ServerID = bms.FK_ServerID
left outer join
(
select
FK_ServerID,
max(backup_set_id) as MaxBackupSetID
from DBAdmin_Central.CentMang.backupset
group by FK_ServerID
) bs
on ss.PK_ServerID = bs.FK_ServerID
where IsOnline = 1
and
(
FK_StackID < 15
or FK_StackID > 15
)
order by ServerName
"
Write-Host "Get list of servers"
$Servers = Invoke-Sqlcmd -ServerInstance 'centralmanagement.p.db.local' `
-Database DBADMIN_Central `
-Query $ServerQuery `
-QueryTimeout 20 `
-OutputSqlErrors $True `
-ConnectionTimeout 5 `
-ErrorAction Continue
Write-Host "Iterate through servers"
#iterate through the list of servers and execute functions for each server
Foreach ($server in $Servers)
{
Write-Host $server.name, $server.id
GetBackupMediaSet $server.name $server.id $server.MaxMediaSetID
GetBackupMediaFamily $server.name $server.id $server.MaxMediaSetID
GetBackupSet $server.name $server.id $server.MaxBackupSetID
GetBackupFile $server.name $server.id $server.MaxBackupSetID
GetBackupFileGroup $server.name $server.id $server.MaxBackupSetID
}
}
function GetBackupMediaSet
{
[CmdletBinding()]
param
(
[string] $server,
[int] $serverid,
[int] $id
)
Write-Host " Get Backup Media Set"
#query we're running
$BMSQuery =
"
SELECT [media_set_id]
,[media_uuid]
,[media_family_count]
,[name]
,[description]
,[software_name]
,[software_vendor_id]
,[MTF_major_version]
,[mirror_count]
,[is_password_protected]
,[is_compressed]
,[is_encrypted]
FROM [msdb].[dbo].[backupmediaset]
where media_set_id > #id
"
#where we're storing query results
$Datatable = New-Object System.Data.DataTable
Write-Host " Get Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='$server'; Database=DBAdmin;Trusted_Connection=True;Connect Timeout=5;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $BMSQuery
$sqlCommand.CommandType = [System.Data.CommandType]::Text
$sqlCommand.CommandTimeout = 5
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $id
$DataReader = $sqlCommand.ExecuteReader()
$Datatable.Load($DataReader)
}
catch
{
Write-Host " Error Getting Backup Media Set"
LogError "Get-BackupHistory" "Get Backup Media Set for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
if ($Datatable.Rows.Count > 0)
{
Write-Host " Insert Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='centralmanagement.p.db.local'; Database=DBAdmin_Central;Trusted_Connection=True;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = "[CentMang].[Insertbackupmediaset_Results]"
$sqlCommand.CommandType = [System.Data.CommandType]::StoredProcedure
$sqlCommand.CommandTimeout = 10
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $serverid
$sqlCommand.Parameters.Add("#results", [System.Data.SqlDbType]::Structured).value = $datatable
$sqlCommand.ExecuteNonQuery()
}
catch
{
Write-Host " Error Inserting Backup Media Set"
LogError "Get-BackupHistory" "Insert Backup Media Set for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
}
else
{
Write-Host " No Results"
}
}
function GetBackupMediaFamily
{
[CmdletBinding()]
param
(
[string] $server,
[int] $serverid,
[int] $id
)
Write-Host " Get Backup Media Family"
#query we're running
$BMFQuery =
"
SELECT [media_set_id]
,[family_sequence_number]
,[media_family_id]
,[media_count]
,[logical_device_name]
,[physical_device_name]
,[device_type]
,[physical_block_size]
,[mirror]
FROM [msdb].[dbo].[backupmediafamily]
where media_set_id > #id
"
#where we're storing query results
$Datatable = New-Object System.Data.DataTable
Write-Host " Get Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='$server'; Database=DBAdmin;Trusted_Connection=True;Connect Timeout=5;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $BMFQuery
$sqlCommand.CommandType = [System.Data.CommandType]::Text
$sqlCommand.CommandTimeout = 5
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $id
$DataReader = $sqlCommand.ExecuteReader()
$Datatable.Load($DataReader)
}
catch
{
Write-Host " Error Getting Backup Media Family"
LogError "Get-BackupHistory" "Get Backup Media Family for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
if ($Datatable.Rows.Count > 0)
{
Write-Host " Insert Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='centralmanagement.p.db.local'; Database=DBAdmin_Central;Trusted_Connection=True;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = "[CentMang].[Insertbackupmediafamily_Results]"
$sqlCommand.CommandType = [System.Data.CommandType]::StoredProcedure
$sqlCommand.CommandTimeout = 10
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $serverid
$sqlCommand.Parameters.Add("#results", [System.Data.SqlDbType]::Structured).value = $datatable
$sqlCommand.ExecuteNonQuery()
}
catch
{
Write-Host " Error Inserting Backup Media Family"
LogError "Get-BackupHistory" "Insert Backup Media Family for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
}
else
{
Write-Host " No Results"
}
}
function GetBackupSet
{
[CmdletBinding()]
param
(
[string] $server,
[int] $serverid,
[int] $id
)
Write-Host " Get Backup Set"
#query we're running
$BSQuery =
"
SELECT [backup_set_id]
,[backup_set_uuid]
,[media_set_id]
,[first_family_number]
,[first_media_number]
,[last_family_number]
,[last_media_number]
,[catalog_family_number]
,[catalog_media_number]
,[position]
,[expiration_date]
,[software_vendor_id]
,[name]
,[description]
,[user_name]
,[software_major_version]
,[software_minor_version]
,[software_build_version]
,[time_zone]
,[mtf_minor_version]
,[first_lsn]
,[last_lsn]
,[checkpoint_lsn]
,[database_backup_lsn]
,[database_creation_date]
,[backup_start_date]
,[backup_finish_date]
,[type]
,[sort_order]
,[code_page]
,[compatibility_level]
,[database_version]
,[backup_size]
,[database_name]
,[server_name]
,[machine_name]
,[flags]
,[unicode_locale]
,[unicode_compare_style]
,[collation_name]
,[is_password_protected]
,[recovery_model]
,[has_bulk_logged_data]
,[is_snapshot]
,[is_readonly]
,[is_single_user]
,[has_backup_checksums]
,[is_damaged]
,[begins_log_chain]
,[has_incomplete_metadata]
,[is_force_offline]
,[is_copy_only]
,[first_recovery_fork_guid]
,[last_recovery_fork_guid]
,[fork_point_lsn]
,[database_guid]
,[family_guid]
,[differential_base_lsn]
,[differential_base_guid]
,[compressed_backup_size]
,[key_algorithm]
,[encryptor_thumbprint]
,[encryptor_type]
FROM [msdb].[dbo].[backupset]
where backup_set_id > #id
"
#where we're storing query results
$Datatable = New-Object System.Data.DataTable
Write-Host " Get Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='$server'; Database=DBAdmin;Trusted_Connection=True;Connect Timeout=5;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $BSQuery
$sqlCommand.CommandType = [System.Data.CommandType]::Text
$sqlCommand.CommandTimeout = 5
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $id
$DataReader = $sqlCommand.ExecuteReader()
$Datatable.Load($DataReader)
}
catch
{
Write-Host " Error Getting Backup Set"
LogError "Get-BackupHistory" "Get Backup Set for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
if ($Datatable.Rows.Count > 0)
{
Write-Host " Insert Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='centralmanagement.p.db.local'; Database=DBAdmin_Central;Trusted_Connection=True;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = "[CentMang].[Insertbackupset_Results]"
$sqlCommand.CommandType = [System.Data.CommandType]::StoredProcedure
$sqlCommand.CommandTimeout = 10
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $serverid
$sqlCommand.Parameters.Add("#results", [System.Data.SqlDbType]::Structured).value = $datatable
$sqlCommand.ExecuteNonQuery()
}
catch
{
Write-Host " Error Inserting Backup Set"
LogError "Get-BackupHistory" "Insert Backup Set for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
}
else
{
Write-Host " No Results"
}
}
function GetBackupFile
{
[CmdletBinding()]
param
(
[string] $server,
[int] $serverid,
[int] $id
)
Write-Host " Get Backup File"
#query we're running
$BFQuery =
"
SELECT [backup_set_id]
,[first_family_number]
,[first_media_number]
,[filegroup_name]
,[page_size]
,[file_number]
,[backed_up_page_count]
,[file_type]
,[source_file_block_size]
,[file_size]
,[logical_name]
,[physical_drive]
,[physical_name]
,[state]
,[state_desc]
,[create_lsn]
,[drop_lsn]
,[file_guid]
,[read_only_lsn]
,[read_write_lsn]
,[differential_base_lsn]
,[differential_base_guid]
,[backup_size]
,[filegroup_guid]
,[is_readonly]
,[is_present]
FROM [msdb].[dbo].[backupfile]
where backup_set_id > #id
"
#where we're storing query results
$Datatable = New-Object System.Data.DataTable
Write-Host " Get Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='$server'; Database=DBAdmin;Trusted_Connection=True;Connect Timeout=5;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $BFQuery
$sqlCommand.CommandType = [System.Data.CommandType]::Text
$sqlCommand.CommandTimeout = 5
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $id
$DataReader = $sqlCommand.ExecuteReader()
$Datatable.Load($DataReader)
}
catch
{
Write-Host " Error Getting Backup File"
LogError "Get-BackupHistory" "Get Backup File for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
if ($Datatable.Rows.Count > 0)
{
Write-Host " Insert Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='centralmanagement.p.db.local'; Database=DBAdmin_Central;Trusted_Connection=True;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = "[CentMang].[Insertbackupfile_Results]"
$sqlCommand.CommandType = [System.Data.CommandType]::StoredProcedure
$sqlCommand.CommandTimeout = 10
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $serverid
$sqlCommand.Parameters.Add("#results", [System.Data.SqlDbType]::Structured).value = $datatable
$sqlCommand.ExecuteNonQuery()
}
catch
{
Write-Host " Error Inserting Backup File"
LogError "Get-BackupHistory" "Insert Backup File for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
}
else
{
Write-Host " No Results"
}
}
function GetBackupFileGroup
{
[CmdletBinding()]
param
(
[string] $server,
[int] $serverid,
[int] $id
)
Write-Host " Get Backup File Group"
#query we're running
$BFGQuery =
"
SELECT [backup_set_id]
,[name]
,[filegroup_id]
,[filegroup_guid]
,[type]
,[type_desc]
,[is_default]
,[is_readonly]
,[log_filegroup_guid]
FROM [msdb].[dbo].[backupfilegroup]
where backup_set_id > '$id'
"
#where we're storing query results
$Datatable = New-Object System.Data.DataTable
Write-Host " Get Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='$server'; Database=DBAdmin;Trusted_Connection=True;Connect Timeout=5;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $BFGQuery
$sqlCommand.CommandType = [System.Data.CommandType]::Text
$sqlCommand.CommandTimeout = 5
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $id
$DataReader = $sqlCommand.ExecuteReader()
$Datatable.Load($DataReader)
}
catch
{
Write-Host " Error Getting Backup File Group"
LogError "Get-BackupHistory" "Get Backup File Group for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
if ($Datatable.Rows.Count > 0)
{
Write-Host " Insert Results"
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server='centralmanagement.p.db.local'; Database=DBAdmin_Central;Trusted_Connection=True;"
$sqlConnection.Open()
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = "[CentMang].[Insertbackupfilegroup_Results]"
$sqlCommand.CommandType = [System.Data.CommandType]::StoredProcedure
$sqlCommand.CommandTimeout = 10
$sqlCommand.Parameters.Add("#id", [System.Data.SqlDbType]::Int).value = $serverid
$sqlCommand.Parameters.Add("#results", [System.Data.SqlDbType]::Structured).value = $datatable
$sqlCommand.ExecuteNonQuery()
}
catch
{
Write-Host " Error Inserting Backup File Group"
LogError "Get-BackupHistory" "Insert Backup File Group for $server" $_.Exception.Message
}
finally
{
$sqlConnection.Close()
}
}
else
{
Write-Host " No Results"
}
}
function LogError
{
[CmdletBinding()]
param
(
[string] $JobName,
[string] $JobStep,
[string] $Error
)
try
{
$sqlConnection = new-object System.Data.SqlClient.SqlConnection
$sqlConnection.ConnectionString = "Server=report.p.db.local; Database=Monitor_Reporting;Trusted_Connection=True;"
$sqlConnection.Open()
$sql = "
Insert into CentMang.ErrorLog (JobName, JobStep, Error)
values (#JobName, #JobStep, #Error)
"
$sqlCommand = new-object System.Data.SqlClient.SqlCommand
$sqlCommand.Connection = $sqlConnection
$sqlCommand.CommandText = $sql
$sqlCommand.CommandType = [System.Data.CommandType]::Text
$sqlCommand.Parameters.Add("#JobName", [System.Data.SqlDbType]::VarChar).value = $JobName
$sqlCommand.Parameters.Add("#JobStep", [System.Data.SqlDbType]::VarChar).value = $JobStep
$sqlCommand.Parameters.Add("#Error", [System.Data.SqlDbType]::VarChar).value = $Error
Write-Host " Insert Error"
$sqlCommand.ExecuteNonQuery()
}
catch
{
Write-Host " Failed to log error"
}
finally
{
$sqlConnection.Close()
}
}
Essentially, I generate a list of servers and iterate through that list. For each server, I go out and get data from a table and save it to a data table. I then check if there are any rows in the data table, and if there are then I insert it into our central report server.
SQL Server looks to be throwing up on checking the data table size, and I'm unsure as to why it would be doing that. I couldn't find anything on this specific issue.
#JosefZ's comment is correct, the issue was using > rather than -gt to compare the data table. Once I fixed that the powershell worked flawlessly.

Connect to SQL Server Database from PowerShell when calling function from function

I am using PowerShell scripts. I have some senior
filter $server and $instance name from .txt file.
Use the $server and $instance in to the 2 function for connect to SQL Server
My .txt file code are as below
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
# Get our list of target servers from the local servers.txt file(Need
$servers = Get-Content 'mirroringserver.txt'
foreach ($prcs in $servers) {
# The first entry in the file is the machine name, the second is the instance name so separate them
#$srvc = $prcs.Split($prcs, "\r\n")
# $ServerName = $prcs
$srvc = $prcs.Split('\')
$servers = $srvc[0]
$instance = $srvc[1]
GetConnectionString $servers $instance
# Ping the machine to see if it's on the network
$results = gwmi -query "select StatusCode from Win32_PingStatus where Address = '$servers'"
$responds = $false
foreach ($result in $results) {
# If the machine responds break out of the result loop and indicate success
if ($result.StatusCode -eq 0) {
$responds = $true
break
}
}
if ($responds) {
# Check to see if a directory exists for this machine, if not create one
if (!(Test-Path -Path .\$servers)) {
New-Item .\$servers\ -Type Directory
}
# Get the server info in the first function and the instance info in the second
#mirroring $servers $instance
getInsertServerStatus $servers $instance
} else {
# Let the user know we couldn't connect to the server
Write-Output "$servers does not respond"
}
}
function GetConnectionString([string]$svr, [string]$inst) {
return "Server=$svr\$inst;Database=master;Integrated Security=True;"
}
This is my function 1:
function mirroring(
$svr,
$inst,
[string] $datastore,
[string] $datastore1,
[string] $datastore2,
[string] $datastore3,
[string] $datastore4,
[string] $datastore5,
[string] $datastore6,
[string] $datastore7
) {
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = GetConnectionString
$SqlConnection.Open()
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = " SELECT db_name(sd.[database_id])AS [Database Name]
,sd.mirroring_state AS [Mirror State Number]
,sd.mirroring_state_desc AS [Mirror State]
,sd.mirroring_partner_name AS [Partner Name]
,sd.mirroring_role_desc AS [Mirror Role]
,sd.mirroring_safety_level_desc AS [Safety Level]
,sd.mirroring_witness_name AS [Witness]
,sd.mirroring_connection_timeout AS [Timeout(sec)]
FROM sys.database_mirroring AS sd
WHERE mirroring_guid IS NOT null
ORDER BY [Database Name];"
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$DataSet.Tables[0]
$SqlConnection.Close()
$datastore = $DataSet.Tables[0].Rows[0][0]
$datastore1 = $DataSet.Tables[0].Rows[0][1]
$datastore2 = $DataSet.Tables[0].Rows[0][2]
$datastore3 = $DataSet.Tables[0].Rows[0][3]
$datastore4 = $DataSet.Tables[0].Rows[0][4]
$datastore5 = $DataSet.Tables[0].Rows[0][5]
$datastore6 = $DataSet.Tables[0].Rows[0][6]
$datastore7 = $DataSet.Tables[0].Rows[0][7]
$script:ServerStatus1 = "DataBase Name:"+ $datastore+",Mirror State Number"+$datastore1+",Mirror State"+$datastore2+",Partner Name"+$datastore3+",Mirror Role"+$datastore4+",Safety Level"+$datastore5+",Witness"+$datastore6+",Timeout(In Sec)"+$datastore7
return $script:ServerStatus1
}
This is my function 2:
function getInsertServerStatus(
$svr1,
$inst2,
$ServerName = $svr1+"\"+$inst2,
$RemActonToBeTaken = 0,
$ServerStatus
) {
mirroring
$Script:ServerStatus1
$Script:ServerStatus= $ServerStatus1
Write-Host "ServerName=$ServerName"
Write-Host "InstanceName=$inst2"
Write-Host "ServerStatus=$ServerStatus1"
Write-Host "RemActonToBeTaken=$RemActonToBeTaken"
$SqlConnection1 = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection1.ConnectionString = "Server=$svr1\$inst2;Database=master;Integrated Security=True;"
$SqlConnection1.Open()
$SqlCmd1 = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd1.CommandText = "USP_RemedialActionDetails"
$SqlCmd1.Connection = $SqlConnection1
$SqlCmd1.CommandType = [System.Data.CommandType]::StoredProcedure
$InParameter1 = New-Object System.Data.SqlClient.SqlParameter;
$InParameter1 = $SqlCmd1.Parameters.Add("#ServerName" , [System.Data.SqlDbType]::String)
$InParameter1.Value = $ServerName
$InParameter1.Direction = [System.Data.ParameterDirection]"Input";
$InParameter2 = New-Object System.Data.SqlClient.SqlParameter;
$InParameter2=$SqlCmd1.Parameters.Add("#InstanceName" , [System.Data.SqlDbType]::String)
$InParameter2.Value = $inst2
$InParameter2.Direction = [System.Data.ParameterDirection]"Input";
$InParameter3 = New-Object System.Data.SqlClient.SqlParameter;
$InParameter3=$SqlCmd1.Parameters.Add("#ServerStatus" , [System.Data.SqlDbType]::String)
$InParameter3.Value = $ServerStatus1
$InParameter3.Direction = [System.Data.ParameterDirection]"Input";
$InParameter4 = New-Object System.Data.SqlClient.SqlParameter;
$InParameter4=$SqlCmd1.Parameters.Add("#RemActionToBeTaken" , [System.Data.SqlDbType]::String)
$InParameter4.Value = $RemActonToBeTaken
$InParameter4.Direction = [System.Data.ParameterDirection]"Input";
$result = $SqlCmd1.ExecuteNonQuery()
Write "result=$result"
$SqlConnection1.Close()
$SQLCmd1.Dispose() | Out-Null
}
I am calling function mirroring inside into function getInsertServerStatus.
Connection string into the function (mirroring) connection error because not found $server and $instance name.
There is some bugs in your code:
first, inside the function getInsertServerStatusyou you call mirroring without passing the parameters $svr $inst ....
it should be:
mirroring $svr1 $inst1 ... other parameters
second, Inside the function **mirroring** you call **GetConnectionString**
without passing parameters $servers $instance
it should be:
GetConnectionString $svr $inst
In the main program you call GetConnectionString $servers $instance and you don't pass the return value to a variable and has no effect in your code, remove this line
Modify your code with the suggested code.

Building a wrapper to perform SQL queries from Powershell

I'm trying to build an all-purpose wrapper to easily query a SQL Server database from within Powershell and work with the results:
$result = SQL("SELECT * CustomerID FROM [dbo].[TblCustomers]")
$result.Tables[0] | Foreach {
Write-Host $_.CustomerID
}
Wrapper
## Wrapper for SQL Select statements
#
Function SQL {
param(
[string]$query
)
$Server = "SQLEXPRESS"
$DBase = "DataStore"
$User = "DataUser"
$Pass = "DataPass"
$conn = New-Object System.Data.SqlClient.SqlConnection("Server=$Server;Database=$DBase;User=$User;Password=$Pass;Connect Timeout=15")
try {
$conn.Open()
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset) | Out-Null
$conn.Close()
}
catch {
$ex = $_.Exception
Write-Error "$ex.Message"
continue
}
return $dataset
}
This only works for SELECT statements however:
If I perform and UPDATE or INSERT, I would like to return the # of rows affected, or an error if applicable
Any other query (ALTER, DROP, DELETE) should be ignored, error message returned
What is the best way to:
Identify the sort of query command (SELECT, DROP)?
Handle all requests in one function? (A switch statement or redirect to specific function?)
Any help is greatly appreciated.
P.S. As I would be the only one using the function in backend scripts, I am not too worried about SQL injection.
[edit]
I now have:
Function Query {
param (
[string]$query
[string]$server
[string]$dbase
[string]$user
[string]$pass
)
if ($user) {
$connstr = "Server={0};Database={1};User ID={2};Password={3};Trusted_Connection=False;Connect Timeout=15" -f $server, $dbase, $user, $pass
}
else {
$connstr = "Server={0};Database={1};Integrated Security=True;Connect Timeout=15" -f $server, $dbase
}
$conn.ConnectionString = $connstr
switch ($query.Split()[0]) {
"SELECT" {
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset) | Out-Null
return $dataset
}
"UPDATE" {
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
return $cmd.ExecuteNonQuery()
}
"INSERT" {
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
return $cmd.ExecuteNonQuery()
}
}
}
Here is a sample you can build from that uses parameter sets to identify query types. The executenonquery method returns the number of rows affected by the query. I use a validatescript attribute to prevent any query containing the words drop, delete, or alter. You can add others as needed. I don't have a SQL box handy to test with but this should work. You could also adjust this to use parameters for the server, db, user, pass, instead of hardcoding them to make it reusable.
function Invoke-SQLQuery
{
[CmdletBinding(DefaultParameterSetName='SELECT',
SupportsShouldProcess=$true,
ConfirmImpact='Medium')]
Param
(
# Param1 help description
[Parameter(Mandatory=$true,
Position=0,
ParameterSetName='SELECT')]
[Parameter(Mandatory=$true,
Position=0,
ParameterSetName='UPDATE')]
[Parameter(Mandatory=$true,
Position=0,
ParameterSetName='INSERT')]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[ValidateScript({$_ -notmatch "ALTER|DROP|DELETE" })]
$Query,
# Param2 help description
[Parameter(ParameterSetName='SELECT')]
[switch]
$Select,
# Param3 help description
[Parameter(ParameterSetName='UPDATE')]
[switch]
$Update,
[Parameter(ParameterSetName='INSERT')]
[switch]
$Insert
)
Begin
{
$Server = "SQLEXPRESS"
$DBase = "DataStore"
$User = "DataUser"
$Pass = "DataPass"
$conn = New-Object System.Data.SqlClient.SqlConnection("Server=$Server;Database=$DBase;User=$User;Password=$Pass;Connect Timeout=15")
}
Process
{
if ($pscmdlet.ShouldProcess("$Server", "Execute Query"))
{
try
{
$conn.Open()
switch($pscmdlet.ParameterSetName){
"SELECT" {
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
$adapter = New-Object System.Data.SqlClient.SqlDataAdapter($cmd)
$dataset = New-Object System.Data.DataSet
$adapter.Fill($dataset) | Out-Null
return $dataset
}
"UPDATE" {
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
return $cmd.ExecuteNonQuery()
}
"INSERT" {
$cmd = New-Object System.Data.SqlClient.SqlCommand($query,$conn)
return $cmd.ExecuteNonQuery()
}
}
}
catch [System.Data.SqlClient.SqlException]
{
#Implement Error Handling
$ex = $_.Exception
Write-Error "$ex.Message"
continue
}
finally
{
$conn.Close()
$conn.Dispose()
}
}
}
}

Import multisheet excel into sql server and export back to a multisheet excel

I have a multi sheet excel workbook with an unknown number of columns in each sheet. I am looping through each sheet and importing the data into a table in sql server. I then am running a query against that table to pull in a few more fields. I then want the result of that query to be exported into a multi sheet excel workbook. I am struggling with how to export this into a multi sheet workbook. In the code below I have it exporting to a csv, but I'm not sure that is the best way to do it. My plan was to then loop through the csvs to create the xlsx, but I could see that causing problems unless I separate everything into their own directories as this will run many times.
Param(
[String]$excelPath,
[String]$serverName,
[String]$databaseName,
[String]$tableName,
[String]$csvPath
)
$ErrorActionPreference = 'Stop'
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO.SqlDataType') | Out-Null
Trap {
$err = $_.Exception
while ( $err.InnerException )
{
$err = $err.InnerException
Write-Output $err.Message
};
exit 1
}
if (test-path $excelTMGPath ) { rm $excelTMGPath } #delete the file if it already exists
$excel = New-Object -ComObject excel.application
$excel.visible = $False
$excel.displayalerts=$False
$workbook = $excel.Workbooks.Open($ExcelPath)
foreach ($ws in $workbook.Worksheets)
{
$workSheet = $ws.Name
Write-Output "Working on worksheet $workSheet"
$query = "select * from [$workSheet`$]";
$connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=`"$excelPath`";Extended Properties=`"Excel 12.0 Xml;HDR=YES;IMEX=1`";"
# Instantiate some objects which will be needed
$serverSMO = New-Object Microsoft.SqlServer.Management.Smo.Server($serverName)
$db = $serverSMO.Databases[$databaseName];
$newTable = New-Object Microsoft.SqlServer.Management.Smo.Table ;
$newTable.Parent = $db;
$newTable.Name = $tableName ;
$conn = New-Object System.Data.OleDb.OleDbConnection($connectionString)
$conn.open()
$cmd = New-Object System.Data.OleDb.OleDbCommand($query,$conn)
$dataAdapter = New-Object System.Data.OleDb.OleDbDataAdapter($cmd)
$dataTable = New-Object System.Data.DataTable
$dataAdapter.fill($dataTable)
$conn.close()
# Drop the table if it exists
if($db.Tables.Contains($tableName).Equals($true))
{
($db.Tables[$tableName]).Drop()
}
# Iterate the columns in the DataTable object and add dynamically named columns to the SqlServer Table object.
foreach($col in $dataTable.Columns)
{
$sqlDataType = [Microsoft.SqlServer.Management.Smo.SqlDataType]::Varchar
$dataType = New-Object Microsoft.SqlServer.Management.Smo.DataType($sqlDataType);
$dataType.MaximumLength = 1000;
$newColumn = New-Object Microsoft.SqlServer.Management.Smo.Column($newTable,$col.ColumnName,$dataType);
$newColumn.DataType = $dataType;
$newTable.Columns.Add($newColumn);
}
$newTable.Create();
#bcp data into new table
$connectionString = "Data Source=$serverName;Integrated Security=true;Initial Catalog=$databaseName;"
$bc = New-Object ("Data.SqlClient.SqlBulkCopy") $connectionString
$bc.DestinationTableName = "$tableName"
$bc.WriteToServer($dataTable)
#Make sure column 3 is named MasterAccountKey for joining purposes
$sqlColumnRename =
#"
USE $databaseName
declare #MasterAccountKey varchar(255), #cmd varchar(500)
set #MasterAccountKey = (select COLUMN_NAME from INFORMATION_SCHEMA.columns
where table_name = 'zzzExcelSheet'
and ordinal_position = 3);
set #cmd = ('sp_RENAME ''zzzExcelSheet.' + #MasterAccountKey + ''', ''MasterAccountKey'', ''COLUMN''')
exec (#cmd)
"#
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Data Source=$serverName;Initial Catalog=$databaseName;Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $sqlColumnRename
$SqlCmd.Connection = $SqlConnection
$SqlConnection.Open()
$sqlCmd.ExecuteNonQuery()
$SqlConnection.Close()
# Connect to SQL and query data, extract data to SQL Adapter
$SqlQuery = #"
select t.*,
b.Social_Security_Number as SSN,
b.PRIMARY_NAME,
b.ADDR_LINE_1,
b.ADDR_LINE_2,
b.CITY,
b.STATE,
b.ZIP_CODE,
from
other tables b
"#
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Data Source=$serverName;Initial Catalog=$databaseName;Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
Try{
$SqlAdapter.SelectCommand = $SqlCmd
}
Catch
{
exit 1
}
$DataSet = New-Object System.Data.DataSet
$nRecs = $SqlAdapter.Fill($DataSet)
$nRecs | Out-Null
#Populate Hash Table
$objTable = $DataSet.Tables[0]
#Export Hash Table to CSV File
$objTable | Export-CSV $objTable | Export-CSV $csvPath -noType
if (test-path $csvPath ) { rm $csvPath }
}
$ws = $null
$workSheet = $null
$workbook.Close()
$workbook = $null
$excel.quit()
while ([System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($excel)) {}
$excel = $null

Resources