SQL to JSON - SQL 2016中的值数组对象数组

Meg*_*mha 27 sql json sql-server-2016

SQL 2016具有一项新功能,可将SQL Server上的数据转换为JSON.我很难将对象数组合成值数组,即

示例 -

CREATE TABLE #temp (item_id VARCHAR(256))

INSERT INTO #temp VALUES ('1234'),('5678'),('7890')

SELECT * FROM #temp

--convert to JSON

SELECT (SELECT item_id 
FROM #temp
FOR JSON PATH,root('ids')) 
Run Code Online (Sandbox Code Playgroud)

结果 -

{
    "ids": [{
        "item_id": "1234"
    },
    {
        "item_id": "5678"
    },
    {
        "item_id": "7890"
    }]
}
Run Code Online (Sandbox Code Playgroud)

但我希望结果如下 -

"ids": [
        "1234",
        "5678",
        "7890"
    ]
Run Code Online (Sandbox Code Playgroud)

有人可以帮帮我吗?

Meg*_*mha 17

谢谢!我们发现的灵魂首先转换为XML -

SELECT  
JSON_QUERY('[' + STUFF(( SELECT ',' + '"' + item_id + '"' 
FROM #temp FOR XML PATH('')),1,1,'') + ']' ) ids  
FOR JSON PATH , WITHOUT_ARRAY_WRAPPER 
Run Code Online (Sandbox Code Playgroud)

  • 我认为由于 FOR XML 查询的性能问题,这不是一个好习惯 (2认同)
  • 我们可以使用 string_escape(item_id, N'json') 来避免产生无效的 json 格式。 (2认同)

Mag*_*dal 12

马丁!

我相信这是一种更简单的方法:

    SELECT '"ids": ' + 
    REPLACE( 
      REPLACE( (SELECT item_id FROM #temp FOR JSON AUTO),'{"item_id":','' ),
      '"}','"' )
Run Code Online (Sandbox Code Playgroud)

  • 这比我见过的任何其他工具都要好得多。不幸的是,这已经达到[功能请求的严重程度](https://connect.microsoft.com/SQLServer/Feedback/Details/1383569)。 (2认同)

mas*_*her 7

declare @temp table (item_id VARCHAR(256))

INSERT INTO @temp VALUES ('123"4'),('5678'),('7890')

SELECT * FROM @temp

--convert to JSON

select 
    json_query(QUOTENAME(STRING_AGG('"' + STRING_ESCAPE(item_id, 'json') + '"', char(44)))) as [json]
from @temp
for json path
Run Code Online (Sandbox Code Playgroud)

当我们想将字符串连接为json数组时:

1)转义字符串-STRING_ESCAPE

2)用逗号分隔符连接字符串-STRING_AGG,逗号ascii代码为44

3)在方括号中添加引号-QUOTENAME(不带参数)

4)返回字符串(带有元素数组)作为json-JSON_QUERY

  • 为什么使用 char(44) 作为逗号而不是文字“,”? (3认同)
  • 虽然这是最干净的解决方案,但这里的“quotename”函数是错误的。它不仅在值周围添加括号,而且根据 SQL 转义规则(而不是 JSON)对其中的右括号“]”进行转义。因此,如果“@temp”中的字符串值包含右括号,它将被错误地转义。正确的方法是`'[' + string_agg(...) + ']'`。 (3认同)
  • 如果您运行的是最新版本的 SQL Server,这是最干净的解决方案。 (2认同)
  • 注意:对于“QUOTENAME()”函数,输入大于 128 个字符将返回 NULL。 (2认同)

Cal*_*ale 6

由于原始值数组是有效的 JSON,因此 SQL Server 的 JSON 功能中没有内置用于选择原始值数组的工具,这似乎很奇怪。(如果相反这样的功能存在,我至少在经过大量搜索后还没有发现它)。

上面概述的方法如描述的那样工作。但是当应用于更大查询中的字段时,原始数组被引号包围。

例如,这个

DECLARE @BomTable TABLE (ChildNumber dbo.udt_ConMetPartNumber);
INSERT INTO @BomTable (ChildNumber) VALUES (N'101026'), (N'101027');
SELECT N'"Children": ' + REPLACE(REPLACE((SELECT ChildNumber FROM @BomTable FOR JSON PATH), N'{"ChildNumber":', N''), '"}','');
Run Code Online (Sandbox Code Playgroud)

通过生产工作:

"Children": ["101026,"101027]
Run Code Online (Sandbox Code Playgroud)

但是,按照上述方法,这是:

SELECT
    p.PartNumber,
    p.Description,
    REPLACE(REPLACE((SELECT
                        ChildNumber
                     FROM
                        Part.BillOfMaterials
                     WHERE
                        ParentNumber = p.PartNumber
                     ORDER BY
                        ChildNumber
                    FOR
                     JSON AUTO
                    ), N'{"ChildNumber":', N''), '"}', '"') AS [Children]
FROM
    Part.Parts AS p
WHERE
    p.PartNumber = N'104444'
FOR
    JSON PATH
Run Code Online (Sandbox Code Playgroud)

产生:

[
    {
        "PartNumber": "104444",
        "Description": "ASSY HUB           R-SER  DRIV HP10  ABS",
        "Children": "[\"101026\",\"101027\",\"102291\",\"103430\",\"103705\",\"104103\"]"
    }
]
Run Code Online (Sandbox Code Playgroud)

孩子阵列封装为一个字符串。

  • 在 REPLACE 周围添加 JSON_QUERY()。这将禁用冗余转义 (6认同)