Powershell invoke-sqlcmd 打印错误的输出
Posted
技术标签:
【中文标题】Powershell invoke-sqlcmd 打印错误的输出【英文标题】:Powershell invoke-sqlcmd Printing The Wrong Output 【发布时间】:2021-12-17 07:25:52 【问题描述】:我有一个按预期运行的 SQL 查询,但是当我尝试在 PowerShell 'Invoke-SqlCmd' 模块中使用它时,输出的结果与查询数据库时不同。我注意到关于这个模块有很多问题,但我找不到适用于我的情况的问题。
查询:
$SQLServer = "localhost"
$query = "SELECT Groups.[Name] AS AGname FROM sys.dm_hadr_availability_group_states States INNER JOIN master.sys.availability_groups Groups ON States.group_id = Groups.group_id WHERE primary_replica = @@Servername"
$HAGName = Invoke-Sqlcmd -query $query -ServerInstance $SQLServer -Database 'database'
if ($HAGName = !$null)
write-host "Availability group name is $HAGName"
exit 0
else
write-host "Failed to retrieve High Availability group name = [$HAGName]"
exit 1
PowerShell 中的输出: 'Availability group name is True'
就像我提到的,当直接查询 SQL Server 时,我得到了正确的输出。我尝试使用“OutputAs”开关,但没有帮助。
任何帮助将不胜感激。
【问题讨论】:
如果没有返回行,您似乎更不理解Invoke-SqlCmd
返回NULL
;那不是真的。如果$query
的值是SELECT name FROM sys.databases WHERE 1 = 0;
,那么$HAGName = !$null
仍然是TRUE。
请注意,您所做的是作业,我认为您的意思是$HAGName -ne $null
,但Larnu 的评论仍然适用。
@Larnu,无论如何我都不是一个 SQL 人,这是我从公司的高级 DBA 那里得到的查询,所以我倾向于认为它应该是可靠的。您能否详细说明您认为命令失败的原因?
-not $null
是 True
并且您将其分配给变量 $HAGName
正如其他人之前评论的那样。将if ($HAGName = !$null)
替换为if ($null -ne $HAGName)
。
【参考方案1】:
所有的指针都在问题的cmet中,但让我系统地分解一下:
!$null
总是 $true
在 PowerShell 中:!
/ -not
,logical NOT operator 将 $null
强制转换为布尔值,并且因为 [bool] $null
是 $false
, ! $null
是 $true
。
$HAGName = !$null
,由于使用了=
,assignment operator,因此将$true
赋值给变量$HAGName
。
-eq
,equality operator。
因此,您打算使用$null -eq $HAGName
(将$null
放在LHS 上,以确保稳健性 - 请参阅the docs)。
但是,鉴于 PowerShell 的隐式到布尔强制规则(请参阅 this answer 的底部部分),您可以在这种情况下简化为 if ($HAGName) ...
。
因此,更多 PowerShell 惯用的代码重新表述是:
$SQLServer = 'localhost'
$query = 'SELECT Groups.[Name] AS AGname FROM sys.dm_hadr_availability_group_states States INNER JOIN master.sys.availability_groups Groups ON States.group_id = Groups.group_id WHERE primary_replica = @@Servername'
$HAGName = Invoke-Sqlcmd -Query $query -ServerInstance $SQLServer -Database database
if ($HAGName)
Write-Verbose -Verbose "Availability group name is: "
# Output the System.Data.DataRow instance as-is,
# which also results in proper for-display formatting.
# If you just want the value of the .AGname property (column), use
# $HAGName.AGname instead.
$HAGName
exit 0
else
Write-Warning "Failed to retrieve High Availability group name."
exit 1
注意:
成功案例隐式将结果输出到成功输出流。
Write-Host
is typically the wrong tool to use,除非意图是仅写入显示器,绕过成功输出流,并能够将输出发送到其他命令,将其捕获到变量中或重定向它到一个文件。要输出一个值,请单独使用它;例如,$value
而不是 Write-Host $value
(或使用 Write-Output $value
,尽管这很少需要);见this answer
我使用了Write-Verbose
调用(默认情况下它的输出是安静的,这里我使用-Verbose
来强制它显示)来提供可选补充/状态信息。
$HAGName
现在(隐式地)输出Invoke-SqlCmd
调用返回的[System.Data.DataRow]
实例原样,这也会导致正确的显示格式 - 这样的实例不 在可扩展(内插字符串)中使用时有意义地字符串化;他们无济于事地字符串化到他们的类型名称,即逐字逐句System.Data.DataRow
。
"Availability group name is $($HAGName | Out-String)"
的内容
【讨论】:
以上是关于Powershell invoke-sqlcmd 打印错误的输出的主要内容,如果未能解决你的问题,请参考以下文章
Powershell invoke-sqlcmd 打印错误的输出
Invoke-sqlcmd 等待恢复完成,然后再进行下一个任务