sqlcmd / Invoke-SqlCmd 中的转义变量

Escape variable in sqlcmd / Invoke-SqlCmd

我正在使用 powershell 并使用 Invoke-SqlCmd。我可以将变量传递给 SQL:

$variables = @( "MyVariable='hello'" )

Invoke-SqlCmd `
    -ServerInstance 'localhost' `
    -Database 'master' `
    -Username 'matthew' `
    -Password 'qwerty' `
    -Query 'SELECT $(MyVariable) AS foo' `
    -Variable $variables

这让我如期返回 hello。但是,如果我有一个变量,其值包含等于 (=):

$variables = @("MyVariable='aGVsbG8NCg=='") # base64 encoded 'hello'

它给我以下错误:

The format used to define the new variable for Invoke-Sqlcmd cmdlet is invalid. Please use the 'var=value' format for defining a new variable.

我找不到任何关于 sqlcmdInvoke-SqlCmd 的文档,说明我应该如何正确转义值。

如何转义发送到 sqlcmd / Invoke-SqlCmd 的变量?

上使用一些反思进行调查后

C:\Program Files (x86)\Microsoft SQL Server0\Tools\PowerShell\Modules\SQLPS\Microsoft.SqlServer.Management.PSSnapins.dll

查看ExecutionProcessor的构造函数,以下几行揭示了如果变量定义中有多个等号会失败的问题。

我对其他尝试使用 Invoke-SqlCmd 的人的建议是节省您的时间和理智,而只使用开源替代方案 Invoke-SqlCmd2

微软,请修复。

我最近遇到了这个问题,并成功使用了 TheMadTechnician 的答案:

Replace Single Quotes in PowerShell Or Excel CSV

The answer is to create sub expressions in your string to replace ' with ''.

Invoke-Sqlcmd -ServerInstance "$SQLServer" -Database "$SqlDB" -query "INSERT INTO dbo.ecca_sw_standard_2 (name, version, product_id) VALUES (N'$($CSVAppName -replace "'", "''")', N'$($CSVVersion -replace "'", "''")' , N'$($CSVAppID -replace "'", "''")')"

This way when the string is expanded it will be appropriately escaped for SQL insertion.

我还发现自己需要传递一段 base64 编码的信息,其中包含那些讨厌的“=”。对我有用的是将替换令牌添加到我传递给查询的变量数组中,然后在我的查询中使用 SQL 的 REPLACE 函数将我的令牌替换为“=”符号。

因此您可以将代码更新为如下所示:

$equalsSignReplacement = '[EQUALSIGN]'
$myVariable = 'aGVsbG8NCg=='
$variables = 
    "EqualsSignReplacement=$($equalsSignReplacement)",
    "MyVariable=$($myVariable.Replace('=',$equalsSignReplacement))"

Invoke-SqlCmd `
    -ServerInstance 'localhost' `
    -Database 'master' `
    -Username 'matthew' `
    -Password 'qwerty' `
    -Query 'SELECT REPLACE('$(MyVariable)','$(EqualsSignReplacement)','=') AS foo' `
    -Variable $variables

此解决方案的缺点是您需要积极主动地应用它。您需要提前知道哪些变量中可能包含 'equals sign',然后不仅更新您的 powershell 代码,还更新您的 SQL 脚本以确保替换正确进行。

请务必使用变量独有的替换标记,以免在查询中不小心将有效文本替换为“=”。

CHAR(61)代替等号。

$variable = "'Hello=World'"
$variables = @( "MyVariable=$($variable.replace("=","'+CHAR(61)+'"))" )

Invoke-SqlCmd -ServerInstance 'localhost' -Database 'master' -Query 'SELECT $(MyVariable) AS foo' -Variable $variables