Powershell invoke-sqlcmd 打印错误的输出

Powershell invoke-sqlcmd Printing The Wrong Output

我有一个 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 服务器时,我得到了正确的输出。我尝试使用 'OutputAs' 开关,但它没有帮助。

任何帮助将不胜感激。

所有的指针都在问题的评论中,但让我系统地分解一下:

  • !$null 在 PowerShell 中是 总是 $true! / -notlogical NOT operator$null 强制转换为布尔值,并且由于 [bool] $null$false! $null$true.

  • $HAGName = !$null,由于使用了=assignment operator,所以将$true赋值给变量$HAGName.

因此,$null -eq $HAGName 是您想要使用的(将 $null 放在 LHS 上,为了稳健性 - 请参阅 the docs) .

但是,考虑到 PowerShell 的隐式 to-Boolean 强制转换规则(参见 的底部部分),您可以在这种情况下简化为 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, unless the intent is to write to the display only, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it by itself; e.g., $value instead of Write-Host $value (or use Write-Output $value, though that is rarely needed); see

    • 我使用了 Write-Verbose 调用(默认情况下它的输出是安静的,这里我使用 -Verbose 强制它显示)来提供 可选补充/状态信息。

    • $HAGName 现在(隐含地)输出 Invoke-SqlCmd 调用 原样 返回的 [System.Data.DataRow] 实例,这也会导致正确的显示格式 - 这样的实例在可扩展(内插字符串)中使用时 not 有意义地进行字符串化;他们毫无帮助地将字符串化为他们的 类型名称 ,即逐字 System.Data.DataRow.

      • 但是,如果您访问行的特定 属性(列),其值 可能 有意义地进行字符串化,取决于 its 数据类型;在您的情况下:`“可用性组名称是 $($HAGName.AGname)”
      • 要在字符串中包含通常的显示格式 - 使用 "Availability group name is $($HAGName | Out-String)"