Sql 用于JSON时,获取值数组而不是对象数组

Sql 用于JSON时,获取值数组而不是对象数组,sql,json,sql-server,tsql,for-json,Sql,Json,Sql Server,Tsql,For Json,我正在尝试展平一个对象数组,它是由JSON的构建的 我的查询如下所示: select ( select id from MyTable where id in (select value from OPENJSON(@jsonArray)) FOR JSON PATH ) existing, ( select value id from OPENJSON(@jsonAr

我正在尝试展平一个对象数组,它是由JSON的
构建的

我的查询如下所示:

select 
(                           
    select id from MyTable
    where id in (select value from OPENJSON(@jsonArray))
    FOR JSON PATH
) existing,                 
(   
    select value id from OPENJSON(@jsonArray) 
    where value not in (select Id from MyTable)
    FOR JSON PATH                       
) missing
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
生成的JSON是:

{
    "existing": [
        {
            "id": "a00cd8f6-d1c6-4604-b235-59d3cacd5bcc"
        },
        {
            "id": "052455b6-6bf5-47d3-8bee-7ba98d7fbd50"
        }
    ],
    "missing": [
        {
            "id": "328add2d-e8f2-4a0e-af54-5b1733310170"
        }
    ]
}
我想要的是:

{
    "existing": [
        {
            "id": "a00cd8f6-d1c6-4604-b235-59d3cacd5bcc"
        },
        {
            "id": "052455b6-6bf5-47d3-8bee-7ba98d7fbd50"
        }
    ],
    "missing": [
        "328add2d-e8f2-4a0e-af54-5b1733310170"            
    ]
}
缺少的数组不应包含json对象,而应包含值。
有什么建议吗?

如果您使用的是SQL Server 2017,您可以使用
JSON\u QUERY
STRING\u AGG
构建您的数组(对于SQL Server 2016,您不能使用
STRING\u AGG
,因此您需要做一些estra工作,但以下想法仍然有效):

结果:

{
  "existing": [
    {
      "id": "a00cd8f6-d1c6-4604-b235-59d3cacd5bcc"
    },
    {
      "id": "052455b6-6bf5-47d3-8bee-7ba98d7fbd50"
    }
  ],
  "missing": [
    "328add2d-e8f2-4a0e-af54-5b1733310170"
  ]
}

这并不像应该的那么容易

抱歉,没有办法用sql server创建一个裸json数组。但您可以在字符串级别上解决此问题:

DECLARE @exist TABLE(id VARCHAR(100));
DECLARE @miss TABLE(id VARCHAR(100));

INSERT INTO @exist VALUES ('exist1'),('exist2');
INSERT INTO @miss VALUES ('miss1'),('miss2');
--这将创建所需的对象数组

SELECT id FROM @exist
FOR JSON PATH
--这将使用一些相当丑陋的技巧创建裸阵列

SELECT REPLACE(REPLACE(REPLACE(
(
    SELECT id from @miss
    FOR JSON PATH
),'"id":',''),'{',''),'}','')
--现在我们必须把两者结合起来。我们需要一个技巧。我们在JSON文本上使用
JSON\u QUERY()
,以避免转义引号

SELECT
(
    SELECT id FROM @exist
    FOR JSON PATH
) AS existing
,JSON_QUERY(
   REPLACE(REPLACE(REPLACE(
    (
        SELECT id from @miss
        FOR JSON PATH
    ),'"id":',''),'{',''),'}','')
) AS missing
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;
这就是结果

{
  "existing":[{"id":"exist1"},{"id":"exist2"}]  <--array of objects
 ,"missing":["miss1","miss2"]                   <--array of naked values
}
{

“existing”:[{“id”:“exist1”},{“id”:“exist2”}]使用从游标追加

DECLARE @missing nvarchar(max),
    @json nvarchar(max) = (select 
                            (                           
                                select id from MyTable
                                where id in (select value from OPENJSON(@jsonArray))
                                FOR JSON PATH
                            ) existing
                            FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)

    DECLARE missing_cursor CURSOR FOR   
        select value id 
        from OPENJSON(@jsonArray)
        where value not in (select Id from MyTable)

        OPEN missing_cursor  

        FETCH NEXT FROM missing_cursor   
        INTO @missing

        WHILE @@FETCH_STATUS = 0  
        BEGIN  
            SET @json = JSON_MODIFY(@json,'append $.missing', @missing)

            FETCH NEXT FROM missing_cursor   
            INTO @missing  
        END   
        CLOSE missing_cursor;  
        DEALLOCATE missing_cursor; 

    select @json

如果
id
包含任何要转义的字符,则
QUOTENAME
将不会生成有效的JSON。我建议改用
'“+STRING”转义(id,'JSON')+'”
(即使在作为GUID的
id
的情况下这并不重要)@jeroemostert没有想到这一点:你完全正确!我更新了我的答案,包括
STRING\u ESCAPE
,谢谢。如果JSON值本身包含
{
}
字符,这将无法正常工作-
替换
将无情地删除这些字符。(没有任何JSON值将包含
“id”:
当然,这还是安全的。)MS SQL Server中的整个JSON功能对我来说似乎不完整。
DECLARE @missing nvarchar(max),
    @json nvarchar(max) = (select 
                            (                           
                                select id from MyTable
                                where id in (select value from OPENJSON(@jsonArray))
                                FOR JSON PATH
                            ) existing
                            FOR JSON PATH, WITHOUT_ARRAY_WRAPPER)

    DECLARE missing_cursor CURSOR FOR   
        select value id 
        from OPENJSON(@jsonArray)
        where value not in (select Id from MyTable)

        OPEN missing_cursor  

        FETCH NEXT FROM missing_cursor   
        INTO @missing

        WHILE @@FETCH_STATUS = 0  
        BEGIN  
            SET @json = JSON_MODIFY(@json,'append $.missing', @missing)

            FETCH NEXT FROM missing_cursor   
            INTO @missing  
        END   
        CLOSE missing_cursor;  
        DEALLOCATE missing_cursor; 

    select @json