我正在使用的库存系统已经改变了存储发票行的方式,正如您在下面看到的,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 作为字符串存储在外部 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 进行演示。