Reputation: 26262
Assuming:
$args = @()
$args += '-E'
$args += "-S 'SERVER'"
$args += "-d 'DATABASE'"
$args += "-Q 'SELECT GetDate() NOW'"
Invoke-Expression "sqlcmd $($args -join ' ')"
produces:
NOW
-----------------------
2015-07-27 16:48:26.387
(1 rows affected)
My attempts at 'splatting' fail.
Invoke-Expression "sqlcmd" @args
andInvoke-Expression 'sqlcmd' @args
andInvoke-Expression sqlcmd @args
produce:`Error: 7/27/2015 4:53:00 PM: At C:\Users\...\default.ps1:34 char:3 + Invoke-Expression "sqlcmd" @args + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ [<<==>>]
Exception: A positional parameter cannot be found that accepts argument '-E'.
& sqlcmd @args
and & 'sqlcmd' @args
produce:
Sqlcmd: '-S 'SERVER'': Unexpected argument. Enter '-?' for help.
What is the correct splatting syntax?
** edit **
Similar pattern (source - Differential backups using 7-zip and PowerShell):
$args = @()
$args += 'a'
$args += "-tZIP"
$args += 'C:\Users\x\Desktop\archive.zip'
$args += 'C:\Users\x\Desktop\a.txt'
& '7z' @args
Results:
7-Zip [64] 9.38 beta Copyright (c) 1999-2014 Igor Pavlov 2015-01-03
Scanning
Updating archive C:\Users\x\Desktop\archive.zip
Compressing a.txt
Everything is Ok
Kernel Time = 0.031 = 63%
User Time = 0.000 = 0%
Process Time = 0.031 = 63% Virtual Memory = 9 MB
Global Time = 0.049 = 100% Physical Memory = 6 MB
What's the difference?
Upvotes: 0
Views: 2127
Reputation: 575
Splatting works with powershell functions and CmdLets. SqlCmd does not support that. You could write a wrapper for SqlCmd and get it to work that way. See the following example.
function SqlCmdWithSplatting
{
param
(
[string]$server,
[string]$database,
[string]$query
)
sqlcmd -E -S $server -d $database -Q $query
}
# Now call that with splatting
$myargs = @{Server="(localdb)\ProjectsV12";database="John";Query="select * from Table1"}
SqlCmdWithSplatting @myargs
Id
-----------
1
2
3
Upvotes: 1
Reputation: 72610
First : I would avoid to give values to $args
which is a Powershell automatic variable reserved for script parameters.
Second : here is the way I use to do it :
$scriptblock = {fullpath\sqlcmd -S `"(local)\instance1`" <# comment option -S #>`
-U a `
-P a `
-i `"c:\temp\sql.sql`" }
Invoke-Command -ScriptBlock $scriptBlock
You can then use $args
variable inside the script block and even start it remotly.
$scriptblock = {fullpath\sqlcmd -S `"(local)\instance1`" <# comment option -S #>`
-U a `
-P a `
-i `"$($args[0])`" }
Invoke-Command -ScriptBlock $scriptBlock -argumentList "c:\temp\sql.sql" -computer "remote1"
Remark :One line per option allow to comment each param, but be careful not to forget a "`" and no space after them when they are at the end of the line.
Upvotes: 0