如何解析T-SQL中转换为字符串的JSON数组

问题描述 投票:0回答:1

我正在使用的库存系统已经改变了存储发票行的方式,正如您在下面看到的,JSON 数组(行)已转换为字符串。

[
    {
        "TaskID": "06896b8d-770e-426f-ac82-000183252c47",
        "InvoiceNumber": "INV-9471D",
        "Lines": "[{\"ProductID\":\"a2540764-3e28-41f0-9ae8-c348a49ee941\",\"SKU\":\"BP13V1\",\"Name\":\"Biodynamic Whole Red Lentils 1kg\",\"Quantity\":1.0,\"Price\":11.95,\"Discount\":0.0,\"Tax\":0.0,\"Total\":11.95,\"AverageCost\":8.9882,\"TaxRule\":\"GST Free Income\",\"Account\":\"202\",\"ProductCustomField10\":\"\"},{\"ProductID\":\"aae9e53e-ad96-493c-99e3-1de193961fa8\",\"SKU\":\"BP6V1\",\"Name\":\"Organic Borlotti Beans 1kg\",\"Quantity\":1.0,\"Price\":9.25,\"Discount\":0.0,\"Tax\":0.0,\"Total\":9.25,\"AverageCost\":5.8832,\"TaxRule\":\"GST Free Income\",\"Account\":\"202\",\"ProductCustomField10\":\"\"}]",
        "TotalBeforeTax": 274.29,
        "Tax": 2.04,
        "Total": 276.33,
        "Paid": 276.33
    }
]

为了解析 JSON 行,我创建了以下脚本,由于上面解释的更改,该脚本现在返回 NULL 而不是特定值:

SELECT
    dbo.Sale.[ID],
    [Invoices_Header].Inv_Number AS Doc_Num,
    [Invoices_Lines].[ProductID],                                           
    [Invoices_Lines].[QTY],
    [Invoices_Lines].[Price],
    [Invoices_Lines].[Discount],
    [Invoices_Lines].[Tax],
    [Invoices_Lines].[TaxRule],
    [Invoices_Lines].[Account]

FROM dbo.Sale

OUTER APPLY OPENJSON([Invoices], '$')
  WITH (
            Inv_Number VARCHAR(100)             '$.InvoiceNumber'

  ) AS [Invoices_Header]


OUTER APPLY OPENJSON([Invoices], '$.Lines')
  WITH (
            ProductID VARCHAR(100)      '$.ProductID',
            SKU VARCHAR(100)            '$.SKU',
            ProductName VARCHAR(100)    '$.Name',
            QTY DECIMAL (8,4)           '$.Quantity',
            Price NUMERIC(19,4)         '$.Price',
            Discount NUMERIC(5,2)       '$.Discount',
            Tax NUMERIC(19,4)           '$.Tax',
            Total NUMERIC(19,4)         '$.Total',
            TaxRule VARCHAR(100)        '$.TaxRule',
            Account VARCHAR(100)        '$.Account',
            AverageCost NUMERIC(19,4)   '$.AverageCost'

  ) AS [Invoices_Lines]

最终结果应该是这样的:

身份证 DOC_NUM 产品_ID 数量 价格 折扣 税收规则 账户 平均成本
06896B8D-770E-426F-AC82-000183252C47 INV-9471D a2540764-3e28-41f0-9ae8-c348a49ee941 1 11.95 0 0 免消费税 202 8.97
06896B8D-770E-426F-AC82-000183252C47 INV-9471D aae9e53e-ad96-493c-99e3-1de193961fa8 1 9.25 0 0 免消费税 202 7.5

而不是这个:

身份证 DOC_NUM 数量 价格 折扣 税收规则 账户 平均成本
06896B8D-770E-426F-AC82-000183252C47 INV-9471D
06896B8D-770E-426F-AC82-000183252C47 INV-9471D

有没有办法修改上面的脚本以正确解析已转换为字符串的 JSON 数组中的值?

问候

大卫

json sql-server parsing
1个回答
0
投票

由于嵌套 JSON 作为字符串存储在外部 JSON 中,因此无法通过解析

Invoices
列直接访问包含的值。相反,您应该添加对外部 JSON 列列表的
'$.Lines'
引用,然后使用
OPENJSON(Invoices_Header.Lines, '$')

在内部 JSON 中引用该列
SELECT
    dbo.Sale.ID,
    Invoices_Header.Inv_Number AS Doc_Num,
    Invoices_Lines.ProductID,                                           
    Invoices_Lines.QTY,
    Invoices_Lines.Price,
    Invoices_Lines.Discount,
    Invoices_Lines.Tax,
    Invoices_Lines.TaxRule,
    Invoices_Lines.Account

FROM dbo.Sale

OUTER APPLY OPENJSON(Invoices, '$')
  WITH (
            Inv_Number VARCHAR(100)             '$.InvoiceNumber',
            Lines      NVARCHAR(MAX)            '$.Lines'  -- *** Added ***

  ) AS Invoices_Header

OUTER APPLY OPENJSON(Invoices_Header.Lines, '$')  -- *** Changed ***
  WITH (
            ProductID VARCHAR(100)      '$.ProductID',
            SKU VARCHAR(100)            '$.SKU',
            ProductName VARCHAR(100)    '$.Name',
            QTY DECIMAL (8,4)           '$.Quantity',
            Price NUMERIC(19,4)         '$.Price',
            Discount NUMERIC(5,2)       '$.Discount',
            Tax NUMERIC(19,4)           '$.Tax',
            Total NUMERIC(19,4)         '$.Total',
            TaxRule VARCHAR(100)        '$.TaxRule',
            Account VARCHAR(100)        '$.Account',
            AverageCost NUMERIC(19,4)   '$.AverageCost'

  ) AS Invoices_Lines

这也可以正确处理外部 JSON 包含多个数组元素的任何情况。内部 JSON 反映当前外部 JSON 元素的

Lines
值(与选定的
InvoiceNumber
匹配。

请参阅 this db<>fiddle 进行演示。

© www.soinside.com 2019 - 2024. All rights reserved.