Remote execute sql script for one server to another - sql-server

I have a "test.sql" in Server1, and I would like to run this script on server2 and server3. I utilized the code below:
$InstanceNm = "server2\inst2,1433"
$CommandExecute_SP = "D:\testscript\test.sql" --located in Server1
invoke-expression "SQLCMD -E -S $InstanceNm -d 'master' -i $CommandExecute_SP -b"
I run the all the codes from server1 and I target server2, but I am getting this error:
SQLCMD : Sqlcmd: 'server2\inst2,1433': Unexpected argument. Enter '-?' for help.
Then when i type -?
It gives this:
At line:1 char:2
+ -?
+ ~
Missing expression after unary operator '-'.
At line:1 char:2
+ -?
+ ~
Unexpected token '?' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingExpressionAfterOperator
I was wondering what the correct way is to run a .sql file which creates objects on another server from a separate server? I know how to run short sql statements via using System.Data.SQLClient.SQLConnection but I would like to avoid that since this .sql file has over 1000 lines of code.

You could create remote sessions and run the command via Invoke-Command-cmdlet.
$sessions = New-PSSession -computername server1, server2, server3
invoke-command -session $sessions -scriptblock {
invoke-expression "SQLCMD -E -S $InstanceNm -d 'master' -i $CommandExecute_SP -b"
}
If you've Win2012 R2 (or higher version) PS-remoting is activated by default. Otherwise take a look at remoting.
Hope that helps

I ran through myscript again and found out that the error was caused by the ' character in the 'master', I omitted this and it is working now.

Related

Powershell script invoked by SQL Agent works differently

I have a pretty simple powershell script (to convert .xlsx files to .xls) like below:
$files = Get-ChildItem "C:\MyFolder\*.xlsx"
foreach ($file in $files) {
$Filepath = Get-Item -Path $file
$NewFilepath = Join-Path -path $Filepath.directory.fullname -ChildPath
"$($Filepath.basename).xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false #or false
$Excel.displayalerts = $false
$Workbook = $Excel.Workbooks.Open("$Filepath".fullname,
[Type]::Missing,$true)
$Workbook.SaveAs("$NewFilepath",56)
#https://technet.microsoft.com/en-us/library/ff730962.aspx
$Workbook.Close()
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
Remove-Variable Excel
Remove-Item $Filepath
}
If I run this script from powershell directly it works just as expected. I mean for each .xlsx file it creates a new .xls file and removes given .xlsx file.
But when I invoke it by SQL Agent all the .xlsx files are simply removed with no creation corresponding .xls files.
SQL Job step
Type: Powershell
Run as: SQL Server Agent service account (checked folder permissioned and is full control)
Command: powershell -File "C:\MyScripts\MyConvertToXls.ps1"
The job does not fail. But when I go to the step execution details I can see the following message:
Message
Executed as user: ServiceAccount. ...rors did not stop the script:
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: 'Sorry, we couldn't find .
Is it possible it was moved, renamed or deleted? '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is:
'At C:\MyScripts\MyConvertToXls.ps1:16 char:1 + $Workbook = $Excel.Workbooks.Open("$Filepath".fullname,[Type]::Missin ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (:) [], COMException '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: ' + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: ' '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: 'You cannot call a method on a null-valued expression. '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: 'At C:\MyScripts\MyConvertToXls.ps1:18 char:1 '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: '+ $Workbook.SaveAs("$NewFilepath",56) '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job.
The error information returned by PowerShell is: '+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'. Correct the script and reschedule the job.
The error information returned by PowerShell is: ' + CategoryInfo : InvalidOperation: (:) [], RuntimeException '
A job step received an error at line 1 in a PowerShell script. The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: ' + FullyQualifiedErrorId : InvokeMethodOnNull '
A job step received an error at line 1 in a PowerShell script. The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"'.
Correct the script and reschedule the job. The error information returned by PowerShell is: ' '
A job step received an error at line 1 in a PowerShell script.
The corresponding line is 'powershell -File "C:\MyScripts\MyConvertToXls.ps1"... Process Exit Code 0. The step succeeded.
A PowerShell job step type expects a script but it looks like you are specifying the OS command powershell -File "C:\MyScripts\MyConvertToXls.ps1" to invoke the script.
Try a Operating System (CmdExec) job step type to invoke the command. Alternatively, paste the script into the PowerShell job step instead of running the external script.
I had same error, and found this solution.
You need to create folder Desktop
C:\Windows\System32\config\systemprofile\Desktop for 32 bit machine
C:\Windows\SysWOW64\config\systemprofile\Desktop for 64 bit machine
It's amaizing but it works

sqlcmd function not throwing the error message if any sql script has an error executing through powershell

Used Sqlcmd function on PowerShell script for multiple SQL scripts execution to get the result as ssms output but through sqlcmd it's not throwing the error message or not able to write catch method if any SQL script has an error, please guide me how I can capture the error if any script has an error.
using Invoke-Sqlcmd command I am not able to capture the script execution output as SSMS has given after execution of any update or insert statement like "1 Rows affected" ,so I need to use sqlcmd command to execute the sql scripts and now all the scripts records are captured but on Invoke-sqlcmd command if any error in the sql scripts its going to the catch block and showing the error but when I am using SQLCMD if there is any error in SQL script it will not go to catch block it statys in the try block and continue .
So please help now how I can capture and move it to catch block or I can capture the error as I have done before using Invoke-SQLCMD command.
this is a continuation of this link :
Not getting ouput after successful execution of the SQL scripts through powershell
Here is my code block and it's not going to catch block :
Try
{
#$result = "Sqlcmd.exe -S $InstanceNAme -d $dbname -Q ""Insert into [DUR2_A].[dbo].[emp_info] values(1,'Ram','Kolkata')"""
#Invoke-Expression $result | Out-File filesystem::$ScriptOutPutpath$scriptfilesc$out
sqlcmd -S $InstanceNAme -i $scriptfiles1 -o $ScriptOutPutpath$scriptfilesc$out -m1
Move-Item filesystem::$scriptfiles1 filesystem::$Scriptbackuppath
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
echo "Error for $scriptfilesc - $($_.Exception.Message)" | Out-File filesystem::$error_log$scriptfilesc$errorout
Send-MailMessage -from test#test.com -To IO-SD.GP.test#test.com -SmtpServer mailrelay.test.com -Subject "DUR Error" -Body "Script $scriptfilesc has not been executed becasue of Error Message $ErrorMessage.Kindly check the attachd script and error message" -Attachments filesystem::$error_log$scriptfilesc$errorout,filesystem::$scriptfiles1
Move-Item filesystem::$scriptfiles1 filesystem::$Scriptbackuppath
}

Powershell Applying SQL Patches Multiple Servers

I need to apply SQL Server Patches in more than 300 Servers, so, I've created code below and saved it as Apply_SQL_Patch.ps1.
I'm reading a txt file with all servers names and I'd like to connect to them, extract and apply Patch.
The issue is when I execute it, it connect to server, but it's not changing directory to D:\Software\Patch, resulting in an error on next lines:
$output = foreach ($cluster in GC "D:\Software\Patch\Servers_List.txt")
{
Enter-PSSession -ComputerName $cluster
cd D:\Software\Patch\
.\SQLServer2014-KB4037356-x64.exe /X:D:\Software\Patch
.\setup.exe /action=patch /instancename=SQL2014 /quiet /IAcceptSQLServerLicenseTerms
}
$output | Out-File -Append D:\Software\Patch\Patch_Result.txt
Error below:
.\SQLServer2014-KB4037356-x64.exe : The term
'.\SQLServer2014-KB4037356-x64.exe' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is
correct and try again. At D:\software\patch\Apply_SQL_Patch.ps1:5
char:2
+ .\SQLServer2014-KB4037356-x64.exe /X:D:\Software\Patch
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (.\SQLServer2014-KB4037356-x64.exe:String) [],
CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
.\setup.exe : The term '.\setup.exe' is not recognized as the name of
a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path
is correct and try again. At D:\software\patch\Apply_SQL_Patch.ps1:7
char:2
+ .\setup.exe /action=patch /instancename=SQL2014 /quiet /IAcceptSQLServerLicense ...
+ ~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (.\setup.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Thanks for your help!
Enter-PSSession -ComputerName $cluster
cd D:\Software\Patch\
.\SQLServer2014-KB4037356-x64.exe /X:D:\Software\Patch
.\setup.exe /action=patch /instancename=SQL2014 /quiet /IAcceptSQLServerLicenseTerms
I don't think this is going to work like you think. You're creating a session and then executing three commands locally.
Try:
Invoke-Command -ComputerName $cluster -ScriptBlock {
cd D:\Software\Patch\
Start-Process -PSPath '.\SQLServer2014-KB4037356-x64.exe' -ArgumentList '/X:D:\Software\Patch' -Wait
.\setup.exe /action=patch /instancename=SQL2014 /quiet /IAcceptSQLServerLicenseTerms
}
I've replaced the patch extraction command with the one above because the command returns control to PowerShell immediately. You may need to do the same thing with setup.exe. I don't have an SQL 2014 instance to test on.

Powershell SQLCMD Mode error

I am trying to run PowerShell Invoke-Sqlcmd but I get an error:
Invoke-Sqlcmd -MaxCharLength 100000 -ServerInstance server1\darabse -InputFile \\server\query.sql
Invoke-Sqlcmd :
At line:6 char:1
+ Invoke-Sqlcmd -MaxCharLength 1000000 -ServerInstance server\database ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Sqlcmd], ParserException
+ FullyQualifiedErrorId : ExecutionFailureException,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand
I can run in in Management studio with SQLCMD Mode.
I have tried everything form here . Any ideas? There is no "$" within it.
I succeed to do i like this, but I am not sure this is solution?
sqlcmd -i \\server\Shared\install\file.sql
Thanks
it works like this:
cmd.exe /C sqlcmd -i \\share\Shared\install_scripts\02SQL\create.sql

Using variables in SQLCMD for Linux

I'm running the Microsoft SQLCMD tool for Linux (CTP 11.0.1720.0) on a Linux box (Red Hat Enterprise Server 5.3 tikanga) with Korn shell. The tool is properly configured, and works in all cases except when using scripting variables.
I have an SQL script, that looks like this.
SELECT COLUMN1 FROM TABLE WHERE COLUMN2 = '$(param1)';
And I'm running the sqlcmd command like this.
sqlcmd -S server -d database -U user -P pass -i input.sql -v param1="DUMMYVALUE"
When I execute the above command, I get the following error.
Sqlcmd: 'param1=DUMMYVALUE': Invalid argument. Enter '-?' for help.
Help lists the below syntax.
[-v var = "value"...]
Am I missing something here?
You don't need to pass variables to sqlcmd. It auto picks from your shell variables:
e.g.
export param1=DUMMYVALUE
sqlcmd -S $host -U $user -P $pwd -d $db -i input.sql
In the RTP version (11.0.1790.0), the -v switch does not appear in the list of parameters when executing sqlcmd -?. Apparently this option isn't supported under the Linux version of the tool.
As far as I can tell, importing parameter values from environment variables doesn't work either.
If you need a workaround, one way would be to concatenate one or more :setvar statements with the text file containing the commands you want to run into a new file, then execute the new file. Based on your example:
echo :setvar param1 DUMMYVALUE > param_input.sql
cat input.sql >> param_input.sql
sqlcmd -S server -d database -U user -P pass -i param_input.sql
You can export the variable in linux. After that you won't need to pass the variable in sqlcmd. However, I did notice you will need to change your sql script and remove the :setvar command if it doesn't have a default value.
export dbName=xyz
sqlcmd -Uusername -Sservername -Ppassword -i script.sql
:setvar dbName --remove this line
USE [$(dbName)]
GO
I think you're just not quoting the input variables correctly. I created this bash script...
#!/bin/bash
# Create a sql file with a parameterized test script
echo "
set nocount on
select k = '-db', v = '\$(db)' union all
select k = '-schema', v = '\$(schema)' union all
select '-', 'static'
go" > ./test.sql
# capture input variables
DB=$1
SCHEMA="${2:-dbo}"
# Exec sqlcmd
sqlcmd -S 'localhost\lemur' -E -i ./test.sql -v "db=${DB}" -v "schema=${SCHEMA}"
... and tested it like so:
$ ./test.sh master
k v
------- ------
-db master
-schema dbo
- static

Resources