1

在 Windows Powershell 中,我有一个简单的Invoke-SqlCmd查询,它返回下表:

ID Text
-- ----
 1 FOO 
 2 BAR 
 3 SPAM

管道它| ConvertTo-Json -Depth 1产生以下结果:

[
    {
        "RowError":  "",
        "RowState":  1,
        "Table":  "",
        "ItemArray":  "1 FOO",
        "HasErrors":  false,
        "ID":  1,
        "Text":  "FOO"
    },
    {
        "RowError":  "",
        "RowState":  1,
        "Table":  "",
        "ItemArray":  "2 BAR",
        "HasErrors":  false,
        "ID":  2,
        "Text":  "BAR"
    },
    {
        "RowError":  "",
        "RowState":  1,
        "Table":  "",
        "ItemArray":  "3 SPAM",
        "HasErrors":  false,
        "ID":  3,
        "Text":  "SPAM"
    }
]

我想要的输出不是这个裸数组,而是一个具有单个属性的对象,该属性具有“产品”作为名称,数组作为值。

此外,我希望我的数组条目是只有 SQL 表的列作为属性的对象。

也就是说,我想要的输出是:

{
    "Products": [
        {
            "ID": 1,
            "Text": "FOO"
        },
        {
            "ID": 2,
            "Text": "BAR"
        },
        {
            "ID": 3,
            "Text": "SPAM"
        }
    ]
}

我怎样才能实现它?


编辑:SQL Server Management Studio 的查询及其结果如下: 在 SSMS 中查询和结果

4

1 回答 1

3

假设$queryResult包含您的Invoke-SqlCmd调用结果:

[pscustomobject] @{ 
  Products = @($queryResult | Select-Object ID, Text)
} | ConvertTo-Json
  • Select-Object创建[pscustomobject]包含仅表示实际表列的属性的实例,在这种情况下是硬编码的。

    • 注意:动态确定这些列名可以提供更通用的解决方案 - 请参阅下一节。
  • @()数组子表达式运算符,确保结果被视为一个数组(以防您的查询恰好返回一行)。

  • [pscustomobject] @{ ... }是用于创建包装器[pscustomobject]实例的语法糖,它的唯一属性 ,Products包含仅列值对象的数组。

  • ConvertTo-Json将生成的自定义对象转换回 JSON。

    • 虽然这里不是问题,但请注意递归深度默认限制为2,需要显式使用-Depth以防止数据丢失 - 请参阅这篇文章

动态确定列名:

Mathias R. Jessen在Fry Simpson的协助下制定了这个解决方案。

通过使Invoke-SqlCmd调用 通过, 返回一个System.Data.Table实例,可用于将查询的列名提取为数组:
-OutputAs DataTables.Column.ColumnNames

# Note the use of `-OutputAs DataTables`; `-As DataTables` should work too.
$queryResult = Invoke-SqlCmd -OutputAs DataTables -Query "SELECT * FROM Schema1.dbo.Table_1" -ServerInstance $instanceName -Database $databaseName  

[pscustomobject] @{ 
  Products = @($queryResult | Select-Object $queryResult.Columns.ColumnName) 
} | ConvertTo-Json 

默认情况下,Invovke-SqlCmd返回单个System.Data.DataRow实例的流。

注意即使$queryResult包含一个System.Data.DataTable实例,它的是如何通过管道隐式发送的;换句话说:$queryResult | ...与 相同$queryResult.Rows | ...,这是 PowerShell 中内置的行为。

于 2020-03-26T12:09:36.587 回答