使用 union 命令为 JSON 个嵌套节点转义
Escaped for JSON nested nodes using union command
在存储过程中我有一个 for json
节点(框):
select
(
select
os.Name,
os.Address,
ss.carrierCode,
(
select
ob.envelopeCode,
ob.boxNumber,
ob.weight,
ob.width,
ob.length,
ob.height
from OrdersBoxes ob
...
where os.OID=ob.OID
...
for json path
) boxes,
....
for json path
) orderDetails
这样我正确得到:
"boxes":[{
"envelopeCode":"E70345D2AB90A879D4F53506FB465086",
"boxNumber":1,
"weight":3000,
"width":300,
"length":300,
"height":100
}]
现在我需要从 2 table 中获取详细信息,因此我将使用 union
命令,将 2 select
包装在另一个 select
查询中以避免以下错误:
The FOR XML and FOR JSON clauses are invalid in views, inline functions, derived tables, and subqueries when they contain a set operator. To work around, wrap the SELECT containing a set operator using derived table or common table expression or view and apply FOR XML or FOR JSON on top of it.
并添加JSON_QUERY
以避免获得转义的嵌套节点:
select
(
select
*
from
(
select
os.Name,
os.Address,
ss.carrierCode,
JSON_QUERY((
select
ob.envelopeCode,
ob.boxNumber,
ob.weight,
ob.width,
ob.length,
ob.height
from OrdersBoxes ob
...
where os.OID=ob.OID
...
for json path
)) boxes,
....
from table1
where....
union
select
os.Name,
os.Address,
ss.carrierCode,
JSON_QUERY((
select
ob.envelopeCode,
ob.boxNumber,
ob.weight,
ob.width,
ob.length,
ob.height
from OrdersBoxes ob
...
where os.OID=ob.OID
...
for json path
)) boxes,
....
from table2
where....
) jj
for json path
) orderDetails
有效,但返回的框节点已转义:
"boxes":"[{\"envelopeCode\":\"E70345D2AB90A879D4F53506FB465086\",\"boxNumber\":1,\"weight\":3000,\"width\":300,\"length\":300,\"height\":100}]"
我也试过这个 Solution 但它只有在从 1 table:
返回数据时才能正常工作
因为它 returns objects
{}
得到一个数组需要改变第一行
select STRING_AGG (order_details,',') ods from (
至
select concat('[',STRING_AGG (order_details,','),']') ods from (
虽然有效,但我似乎不是很“优雅”。
有人可以建议一种更好的方法来正确格式化所有数据(因此未转义框节点)吗?
关于 JSON_QUERY()
explains 的文档:... JSON_QUERY return 是一个有效的 JSON 片段。因此,FOR JSON 不会转义 JSON_QUERY return 值中的特殊字符。如果您 return 使用 FOR JSON 计算结果,并且您要包括已经采用 JSON 格式的数据(在列中或作为表达式的结果),请将 JSON 数据 JSON_QUERY 没有路径参数。。所以,如果我正确理解架构,你需要以不同的方式使用 JSON_QUERY()
:
表:
SELECT *
INTO table1
FROM (VALUES
(1, 'Name1', 'Address1')
) v (oid, name, address)
SELECT *
INTO table2
FROM (VALUES
(2, 'Name2', 'Address2')
) v (oid, name, address)
SELECT *
INTO OrdersBoxes
FROM (VALUES
(1, 'E70345D2AB90A879D4F53506FB465086', 1, 3000, 300, 300, 100),
(2, 'e70345D2AB90A879D4F53506FB465086', 2, 3000, 300, 300, 100)
) v (oid, envelopeCode, boxNumber, weight, width, length, height)
声明:
select Name, Address, JSON_QUERY(boxes) AS Boxes
from (
select
os.Name,
os.Address,
(
select ob.envelopeCode, ob.boxNumber, ob.weight, ob.width, ob.length, ob.height
from OrdersBoxes ob
where os.OID = ob.OID
for json path
) boxes
from table1 os
union all
select
os.Name,
os.Address,
(
select ob.envelopeCode, ob.boxNumber, ob.weight, ob.width, ob.length, ob.height
from OrdersBoxes ob
where os.OID = ob.OID
for json path
) boxes
from table2 os
) j
for json path
作为附加选项,您可以尝试使用 FOR JSON AUTO
(JSON 输出的格式是根据 SELECT
列表中列的顺序及其对应的顺序自动确定的源表):
SELECT
cte.Name, cte.Address,
boxes.envelopeCode, boxes.boxNumber, boxes.weight, boxes.width, boxes.length, boxes.height
FROM (
SELECT oid, name, address FROM table1
UNION ALL
SELECT oid, name, address FROM table2
) cte
JOIN OrdersBoxes boxes ON cte.oid = boxes.oid
FOR JSON AUTO
结果:
[
{
"Name":"Name1",
"Address":"Address1",
"boxes":[{"envelopeCode":"E70345D2AB90A879D4F53506FB465086","boxNumber":1,"weight":3000,"width":300,"length":300,"height":100}]
},
{
"Name":"Name2",
"Address":"Address2",
"boxes":[{"envelopeCode":"e70345D2AB90A879D4F53506FB465086","boxNumber":2,"weight":3000,"width":300,"length":300,"height":100}]
}
]
在存储过程中我有一个 for json
节点(框):
select
(
select
os.Name,
os.Address,
ss.carrierCode,
(
select
ob.envelopeCode,
ob.boxNumber,
ob.weight,
ob.width,
ob.length,
ob.height
from OrdersBoxes ob
...
where os.OID=ob.OID
...
for json path
) boxes,
....
for json path
) orderDetails
这样我正确得到:
"boxes":[{
"envelopeCode":"E70345D2AB90A879D4F53506FB465086",
"boxNumber":1,
"weight":3000,
"width":300,
"length":300,
"height":100
}]
现在我需要从 2 table 中获取详细信息,因此我将使用 union
命令,将 2 select
包装在另一个 select
查询中以避免以下错误:
The FOR XML and FOR JSON clauses are invalid in views, inline functions, derived tables, and subqueries when they contain a set operator. To work around, wrap the SELECT containing a set operator using derived table or common table expression or view and apply FOR XML or FOR JSON on top of it.
并添加JSON_QUERY
以避免获得转义的嵌套节点:
select
(
select
*
from
(
select
os.Name,
os.Address,
ss.carrierCode,
JSON_QUERY((
select
ob.envelopeCode,
ob.boxNumber,
ob.weight,
ob.width,
ob.length,
ob.height
from OrdersBoxes ob
...
where os.OID=ob.OID
...
for json path
)) boxes,
....
from table1
where....
union
select
os.Name,
os.Address,
ss.carrierCode,
JSON_QUERY((
select
ob.envelopeCode,
ob.boxNumber,
ob.weight,
ob.width,
ob.length,
ob.height
from OrdersBoxes ob
...
where os.OID=ob.OID
...
for json path
)) boxes,
....
from table2
where....
) jj
for json path
) orderDetails
有效,但返回的框节点已转义:
"boxes":"[{\"envelopeCode\":\"E70345D2AB90A879D4F53506FB465086\",\"boxNumber\":1,\"weight\":3000,\"width\":300,\"length\":300,\"height\":100}]"
我也试过这个 Solution 但它只有在从 1 table:
返回数据时才能正常工作因为它 returns objects
{}
得到一个数组需要改变第一行
select STRING_AGG (order_details,',') ods from (
至
select concat('[',STRING_AGG (order_details,','),']') ods from (
虽然有效,但我似乎不是很“优雅”。
有人可以建议一种更好的方法来正确格式化所有数据(因此未转义框节点)吗?
关于 JSON_QUERY()
explains 的文档:... JSON_QUERY return 是一个有效的 JSON 片段。因此,FOR JSON 不会转义 JSON_QUERY return 值中的特殊字符。如果您 return 使用 FOR JSON 计算结果,并且您要包括已经采用 JSON 格式的数据(在列中或作为表达式的结果),请将 JSON 数据 JSON_QUERY 没有路径参数。。所以,如果我正确理解架构,你需要以不同的方式使用 JSON_QUERY()
:
表:
SELECT *
INTO table1
FROM (VALUES
(1, 'Name1', 'Address1')
) v (oid, name, address)
SELECT *
INTO table2
FROM (VALUES
(2, 'Name2', 'Address2')
) v (oid, name, address)
SELECT *
INTO OrdersBoxes
FROM (VALUES
(1, 'E70345D2AB90A879D4F53506FB465086', 1, 3000, 300, 300, 100),
(2, 'e70345D2AB90A879D4F53506FB465086', 2, 3000, 300, 300, 100)
) v (oid, envelopeCode, boxNumber, weight, width, length, height)
声明:
select Name, Address, JSON_QUERY(boxes) AS Boxes
from (
select
os.Name,
os.Address,
(
select ob.envelopeCode, ob.boxNumber, ob.weight, ob.width, ob.length, ob.height
from OrdersBoxes ob
where os.OID = ob.OID
for json path
) boxes
from table1 os
union all
select
os.Name,
os.Address,
(
select ob.envelopeCode, ob.boxNumber, ob.weight, ob.width, ob.length, ob.height
from OrdersBoxes ob
where os.OID = ob.OID
for json path
) boxes
from table2 os
) j
for json path
作为附加选项,您可以尝试使用 FOR JSON AUTO
(JSON 输出的格式是根据 SELECT
列表中列的顺序及其对应的顺序自动确定的源表):
SELECT
cte.Name, cte.Address,
boxes.envelopeCode, boxes.boxNumber, boxes.weight, boxes.width, boxes.length, boxes.height
FROM (
SELECT oid, name, address FROM table1
UNION ALL
SELECT oid, name, address FROM table2
) cte
JOIN OrdersBoxes boxes ON cte.oid = boxes.oid
FOR JSON AUTO
结果:
[
{
"Name":"Name1",
"Address":"Address1",
"boxes":[{"envelopeCode":"E70345D2AB90A879D4F53506FB465086","boxNumber":1,"weight":3000,"width":300,"length":300,"height":100}]
},
{
"Name":"Name2",
"Address":"Address2",
"boxes":[{"envelopeCode":"e70345D2AB90A879D4F53506FB465086","boxNumber":2,"weight":3000,"width":300,"length":300,"height":100}]
}
]