JSON-如何在SQL中将数组追加到数组

时间:2018-12-21 16:25:47

标签: sql json sql-server tsql sql-server-2016

我在一个表中有一个json字段,其中包含这样的数组:-

[
  {
    "ID": 11111,
    "Name": "apple",
  },
  {
    "ID": 22222,
    "Name": "orange",
  },
  {
    "ID": 333333,
    "Name": "banana",
  } 
] 

我想将以下json数组附加/连接到此数组:-

[
  {
    "ID": 44444,
    "Name": "grape",
  },
  {
    "ID": 55555,
    "Name": "kiwi",
  },
  {
    "ID": 66666,
    "Name": "fig",
  } 
] 

这样我最终在表字段中找到了它:-

[
  {
    "ID": 11111,
    "Name": "apple",
  },
  {
    "ID": 22222,
    "Name": "orange",
  },
  {
    "ID": 333333,
    "Name": "banana",
  },
  {
    "ID": 44444,
    "Name": "grape",
  },
  {
    "ID": 55555,
    "Name": "kiwi",
  },
  {
    "ID": 66666,
    "Name": "fig",
  } 
] 

即我在现有的三个元素中添加了三个新元素,这样我的表字段中现在有了一个包含六个元素的单个数组。

我一直在尝试使用JSON_MODIFY进行这项工作,并成功将单个元素添加到数组中,如下所示:-

select JSON_MODIFY(json_field,'append $', JSON_QUERY('{ "ID": 44444, "Name": "grape" }'))

但是我不能让它在单个操作中附加多个元素并使其看起来像期望的那样,我一直在尝试这种变化:-

select JSON_MODIFY(json_field,'append $', JSON_QUERY('[{ "ID": 44444, "Name": "grape" }, { "ID": 55555, "Name": "kiwi" }, { "ID": 66666, "Name": "fig" }]'))

在这种情况下,它用方括号附加,因此三个新元素最终成为子数组!

是否可以像这样将一个数组的多个元素附加到另一个数组? (我真的很胖,缺少明显的东西吗?!?)

4 个答案:

答案 0 :(得分:6)

来自the documentation

  

示例-多个更新:使用JSON_MODIFY您只能更新一个   属性。如果必须进行多个更新,则可以使用多个   JSON_MODIFY调用。

这意味着循环,这是我要避免的事情...

我建议使用简单的字符串操作或分解/重新组合:

DECLARE @json1 NVARCHAR(MAX)=
N'[
  {
    "ID": 11111,
    "Name": "apple"
  },
  {
    "ID": 22222,
    "Name": "orange"
  },
  {
    "ID": 333333,
    "Name": "banana"
  } 
]'; 
DECLARE @json2 NVARCHAR(MAX)=
N'[
  {
    "ID": 44444,
    "Name": "grape"
  },
  {
    "ID": 55555,
    "Name": "kiwi"
  },
  {
    "ID": 66666,
    "Name": "fig"
  } 
]';

-这将从派生表中重新创建JSON

SELECT t.ID,t.[Name]
FROM
(
    SELECT * FROM OPENJSON(@json1) WITH(ID int,[Name] NVARCHAR(MAX)) 
    UNION ALL
    SELECT * FROM OPENJSON(@json2) WITH(ID int,[Name] NVARCHAR(MAX))
) t
FOR JSON PATH;

-这将创建一个裸数组并将其STUFF()放置到正确位置

DECLARE @NakedArray NVARCHAR(MAX)=N',' +
(
    SELECT A.* 
    FROM OPENJSON(@json2)
    WITH(ID int, Name NVARCHAR(MAX)) A
    FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
);

SELECT STUFF(@json1,LEN(@json1)-1,0,@NakedArray);

裸数组您可以简单地通过用逗号替换[并切掉]来实现...

更新:一种最小的方法

尝试这种最小的方法:

SELECT REPLACE(@json1,']',REPLACE(@json2,'[',','));

答案 1 :(得分:3)

尝试一下:

DECLARE @j1 AS NVARCHAR(MAX) = '[
  {
    "ID": 11111,
    "Name": "apple"
  },
  {
    "ID": 22222,
    "Name": "orange"
  },
  {
    "ID": 333333,
    "Name": "banana"
  } 
] ';


DECLARE @j2 AS NVARCHAR(MAX) = '
[
  {
    "ID": 44444,
    "Name": "grape"
  },
  {
    "ID": 55555,
    "Name": "kiwi"
  },
  {
    "ID": 66666,
    "Name": "fig"
  } 
] ';


SELECT * FROM
(
SELECT [ID], [Name] FROM  OPENJSON(@j1) WITH (ID INT, [Name] NVARCHAR(200))
UNION
SELECT  [ID], [Name]  FROM  OPENJSON(@j2) WITH (ID INT, [Name] NVARCHAR(200))
) x
FOR JSON AUTO 

答案 2 :(得分:0)

我遇到了同样的问题。我发现自己的解决方案非常不文明。但是似乎没有什么比这更好了。

xsl:sequence

答案 3 :(得分:-1)

以下内容扩展了先前的解决方案,以适用于任意对象/数组/值的JSON数组的并集,即使字符串值包含字符[或]。但是,该解决方案使用STRING_AGG函数,因此需要SQL Server 2017及更高版本。

    DECLARE @json1 NVARCHAR(MAX)=
N'[
  {
    "ID": 11111,
    "Name": "apple"
  },
  {
    "ID": 22222,
    "Number": 1234
  },
  {
    "ID": 333333,
    "Names": ["apple", "banana"]
  } 
]'; 
DECLARE @json2 NVARCHAR(MAX)=
N'[
  {
    "Random": "grape"
  },
  [
    123,
    456
  ],
  "f[i]g"
]';

SELECT CONCAT(
    N'[',
        (
        SELECT STRING_AGG(U.[value],N',') WITHIN GROUP (ORDER BY U.ArrayNo ASC,U.[key] ASC)
            FROM
                (
                SELECT 1 AS ArrayNo,[key],[value] FROM OPENJSON(@JSON1)
                UNION ALL
                SELECT 2 AS ArrayNo,[key],[value] FROM OPENJSON(@JSON2)
                ) AS U
            ),
    N']'
    )