sql-server - Powershell invoke-sqlcmd 打印错误的输出
问题描述
我有一个按预期运行的 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 中的输出: “可用性组名称为 True”
就像我提到的,当直接查询 SQL Server 时,我得到了正确的输出。我尝试使用“OutputAs”开关,但没有帮助。
任何帮助将不胜感激。
解决方案
所有的指针都在问题的评论中,但让我系统地分解它:
!$null
始终在$true
PowerShell:!
/-not
中,逻辑 NOT 运算符强制$null
转换为布尔值,并且由于[bool] $null
is$false
,! $null
is$true
。$HAGName = !$null
,由于使用=
了赋值运算符,因此赋值$true
给变量$HAGName
。- 要改为执行相等比较
-eq
,请使用相等运算符。
- 要改为执行相等比较
因此,$null -eq $HAGName
这就是您要使用的内容(将$null
放在LHS上,以实现稳健性 - 请参阅文档)。
但是,鉴于 PowerShell 的隐式到布尔强制规则(请参阅此答案的底部部分),您可以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
通常是使用错误的工具,除非意图是仅写入显示,绕过成功输出流,并且能够将输出发送到其他命令,将其捕获到变量中,或将其重定向到文件。要输出一个值,请单独使用它;例如,$value
代替Write-Host $value
(或使用Write-Output $value
,尽管很少需要);看到这个答案我使用了一个
Write-Verbose
调用(默认情况下它的输出是安静的,这里我用来-Verbose
强制它显示)来提供可选的补充/状态信息。$HAGName
现在(隐式)按原样输出调用[System.Data.DataRow]
返回的实例,这也导致正确的显示格式 -当在可扩展(插值字符串)中使用时,此类实例不会有意义地字符串化;他们无助地字符串化到他们的类型名称,即逐字逐句。Invoke-SqlCmd
System.Data.DataRow
- 但是,如果您访问行的特定属性(列),则其值可能会有意义地字符串化,具体取决于其数据类型;在您的情况下:`“可用性组名称是 $($HAGName.AGname)”
- 要在字符串中包含通常的显示格式 - 使用类似
"Availability group name is $($HAGName | Out-String)"
推荐阅读
- sql - 有没有办法在熊猫数据框中运行 posqresql 查询?
- javascript - 更新 react-sortable-tree 中的节点
- java - 重定向到带有连字符的 URL 在 Spring Gateway 应用程序中不起作用
- python - Pytorch CNN 损失没有改变
- excel - 具有动态范围/边界的循环
- python - 使用 CrossHair 区分自动机和 python 函数
- csh - 如何设置我的 tcsh 提示符以显示上一个命令的执行时间?
- node.js - Rails 6 - 我的应用程序中的 node_modules 文件夹是什么?
- reactjs - React:如何打开卡片的特定编辑/删除窗口?
- javascript - 无法离开会话,本地媒体已在 Safari 中停止 - IceLink 3