Escape double quotes in command parameter - sql-server

I need to run a PS command on SQL Server. Running a simple command without double-quotes works without a problem.
How to run below command?
DECLARE #sql nvarchar(4000);
SET #sql =
'
powershell.exe -command "
$messageBody = "ds"
Write-Host $messageBody
"';
EXEC xp_cmdshell #sql;
I tried this ` and backslash but nothing seems to be working.
Running it from ps1 file is not an option.

Instead of "ds", use ''ds'' to use single quotes withing the ps script to enclose the literal. Furthermore, use the call operator (&) withing the command parameter to call the script block:
SET #sql = 'powershell.exe -command "& { $messageBody = ''ds''; Write-Host $messageBody }';

Related

How can I execute a SQL Server stored procedure from a Batch file and get the Output parameter value?

I have this SQL Server stored procedure that has an output parameter
PROCEDURE [dbo].[test]
#outputx int output
AS
SELECT #outputx = 123
When I run it in SQL Server Management Studio, it returns 123:
DECLARE #outputx int
EXEC test #outputx output
SELECT #outputx --> returns 123
I need to call this stored procedure from a batch file or PowerShell.
I use this code in a .BAT file (I use OSQL):
SET tempfile = "C:\myFolder\tempfile.txt"
SET outputx = 0
SET Cmd = EXEC test #outputx output;
SET Cmd = "%Cmd%"
OSQL -S myDBServer -d myDbName -E -e -p -b -Q %Cmd% >%tempfile%
When I checked tempfile.txt, it says this:
Msg 137, Level 15, State 2, Server myDBServer, Line 1
Must declare the scalar variable "#outputx".
EXEC test #outputx output;
How can I execute a SQL Server stored procedure from a batch file and get the output parameter value?
Thank you
Have you tried the SqlServer module for PowerShell? After installing that module, you have access to the Invoke-SqlCmd cmdlet. You can use this cmdlet to retrieve anything that will run in SQLMgr.
$ReturnValue = invoke-sqlcmd -ServerInstance $ServerInstance -Database $Database -Query $QueryString
There are other commands in that module including commands to read and write tables and views.
I hope this helps you out.

How to get escape characters to behave through sql server's xp_cmdshell with command with Caret

I'm trying to print from a SQL Server stored procedure to a Label printer using ZPL with variables and a network printer
I've tested the ZPL to make sure it's working and then learned how to pass it through a PowerShell script to get it to print to the correct network printer and its working but I'm stumbling trying to get the command to run in SQL server's xp_cmdshell.
DECLARE #Pickloc varchar(6)
DECLARE #powershell varchar(2000)
print #powershell
set #Pickloc = 'PCK002'
set #powershell = 'powershell.exe -command """"^XA ^LH0,50^FS ^PR4,4 ^LL2233 ^CI0^FT20,15^A0N,20,20^FDBACKSTOCK^FS ^CI0^FT180,30^A0N,65,65^FDPick Loc: PCK002^FS ^FO50,50^GB700,1,3^FS ^CI0^FT50,114^A0N,65,65^FDSKU: 91007419^FS ^CI0^FT50,184^A0N,65,65^FDBackstock Loc: FL0002^FS ^FO50,200^GB700,1,3^FS ^CI0^FT50,270^A0N,48,48^FDDriver: Driver^FS ^CI0^FT50,330^A0N,48,48^FDFrom Loc: ABC001^FS ^CI0^FT475,330^A0N,48,48^FDTAG: T123456^FS ^XZ""" | Out-Printer -NAME """\\PrintServer\MyPrinter"""""'
print #powershell
EXEC master..xp_cmdshell #powershell
I'm expecting the string to get passed to PowerShell and print the ZPL.
I'm running into issues I think with windows cmd's escape character "^"
I'd also like to pass the variable #Pickloc inside the ZPL but I can't get past this part first.
I never got an answer but instead of injection the zpl into the powershell command via xp_cmdshell I resorted to creating a text file with the zpl with the variables then calling that file in powershell. Automatically

Powershell SQL Server Agent CmdExec job step multiple line code

Why does code like this execute in PowerShell ISE:
$var = 'dog';Invoke-SqlCmd -ServerInstance 'servername' -Query "insert into DB.dbo.tbl values ('$($var)')"
But not in SQL Server Agent as a CmdExec job step? Despite enclosing it as per usual. I believe it is the multiple queries as individual queries work
powershell.exe -ExecutionPolicy Bypass -Command {$var = 'dog';Invoke-SqlCmd -ServerInstance 'servername' -Query "insert into DB.dbo.tbl values ('$($var)')"}
TL;DR;
I have a SQL Server Agent job with a CmdExec step. I wish to assign a variable and then use it in an insert statement.
So far the following insert will work:
powershell.exe -ExecutionPolicy Bypass -Command "Invoke-SqlCmd -ServerInstance 'servername' -Query 'insert into DB.dbo.tbl values (''cat'')'"
This inserts a cat. Now I need a dog, something along the lines of:
powershell.exe -ExecutionPolicy Bypass -Command "$var = 'dog'; Invoke-SqlCmd -ServerInstance 'servername' -Query ""insert into DB.dbo.tbl values (''$($var)'')"""
There are two issues here, the comma terminator which I have used successfully in other jobs to separate commands. The second issue is escaping the double quotes. I understand they are required to process the variable into the string.
I have tried escaping with double quotes as well as one of these `. I've also tried separating the variable declaration into one server agent job step and using the variable in another.
Based on #gvee answer below, I put the code in a script block, which executes perfectly in PowerShell, but not as a SQL Agent CmdExec job step
powershell.exe -ExecutionPolicy Bypass -Command {$var = '''dog'''; Invoke-SqlCmd -ServerInstance 'servername' -Query "insert into DB.dbo.tbl values ($($var))"}
Note I had to escape the variable three times, which inserted into the table as 'dog' with the quotes included. I removed the single quotes from the insert statement, however I cannot get this to run in Server Agent as a CmdExec step
-Command accepts a ScriptBlock, so give this a whirl:
powershell.exe -ExecutionPolicy Bypass -Command {
Invoke-SqlCmd -ServerInstance "servername" -Query "insert into DB.dbo.tbl values ('cat')"
}

Server Agent PowerShell job step - Difference between calling a file and calling a command

I have some simple PowerShell code to insert a value into a table:
Invoke-SqlCmd -ServerInstance myserver -Query 'insert into Database.dbo.tbl values (1)'
and if I save it as a file, I can call it in a CmdExec job step. However, can anyone tell me why I can't run the command, especially as it is only one line:
powershell.exe -ExecutionPolicy Bypass -Command 'Invoke-Sqlcmd -ServerInstance myserver -Query ''insert into DBADatabase.dbo.tbl values (1)'''
Can anyone tell me why running as a command will not work, yet the same code as a file can work. Any help appreciated.
Thanks
Your powershell.exe ... command is executed from outside PowerShell, possibly via cmd.exe.
In that case, '...'-enclosed strings have no syntactical function and are passed straight through to PowerShell, causing it to interpret them as enclosing a string literal, which is simply output as-is (in other words: your command is printed rather than executed).
Instead, you must use "..." to enclose the command to pass to PowerShell; inside that string, you're free to use '...':
powershell.exe -ExecutionPolicy Bypass -Command "Invoke-Sqlcmd -ServerInstance myserver -Query 'insert into DBADatabase.dbo.tbl values (1)'"
I have create test job on my server with below powershell code and it work. Below image have my job detail.
My Test code
Invoke-Sqlcmd -ServerInstance 'MYSERVER' -Query 'insert into DBA_TOOLS.dbo.tbl values (1)'
your code - you are missing single quotes 'myserver' around sql server.
Invoke-Sqlcmd -ServerInstance 'myserver' -Query ''insert into DBADatabase.dbo.tbl values (1)'
hope this help

How to pass variable to bcp command within powershell script

I am creating a string that I would like to pass to the bcp command from within a PowerShell script. Here is the code that creates the string
$fullFilePath = (pwd).path + "\$db.$table" + ".dat"
$copyExecString = "bcp $db.$table out $fullFilePath -E -N -Slocalhost"
I can paste the Write-host result of this into a command prompt and it runs just fine, but it won't work as follows:
$fullFilePath = (pwd).path + "\$db.$table" + ".dat"
$copyExecString = "$db.$table out $fullFilePath -E -N -Slocalhost"
bcp $copyExecString
I also tried using the ampersand character before calling the bcp command, but to no avail
Any ideas on how to achieve this functionality would be greatly appreciated
Instead of a single string, tokenize it by splitting the arguments out by spaces:
& bcp $db.$table out $fullFilePath -E -N -Slocalhost
you can use Invoke-Expression cmdlet to ensure that you parse what you want to execute prior to execution:
Invoke-Expression "bcp $copyExecString"

Resources