【问题标题】:JSON - How to append an array to an array in sqlJSON - 如何将数组附加到sql中的数组
【发布时间】:2018-12-21 16:25:46
【问题描述】:

我的表中有一个 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" }]'))

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

是否可以像这样将一个数组的多个元素附加到另一个数组? (我是不是真的很厚,错过了什么明显的东西?!?)

【问题讨论】:

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


    【解决方案1】:

    来自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,'[',','));
    

    【讨论】:

    • 最小的方法非常漂亮:)
    • 感谢您的提醒,学习新事物永远不会失败。 (删除了我的答案,因为你的答案是一样的。)
    • 哇,谢谢大家这么快的回复!!我昨天晚上发了帖子然后直接出去吃晚饭,然后直到几个小时后我回来才再次检查它,以为没有人会读它更不用说回答它了(我是stackoverflow的新手,过去一直在使用其他论坛,其中响应速度有点慢;-)。无论如何回到答案 - 哦!我完全认为你可以用 json_modify 来做到这一点,而我只是错过了显而易见的事情(即使是显而易见的事情实际上是文档告诉我它无法完成!)。
    • 使用 union 听起来很理想,但我真的很喜欢最小方法的简单性,所以我会使用它并保留 union,因为我有很多 json crud 要做,所以我相信它会来有用:)
    • 这些方法适用于问题中的简单情况,但不适用于任意对象的数组。最小的方法确实很漂亮,但是当要组合的数组包含带有 [ 或 ] 和/或内部数组的字符串值时会失败。
    【解决方案2】:

    试试这个:

    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 
    

    【讨论】:

    • 我投了你的票,因为你的速度快了几秒钟,但你可能会检查我的最后一行 ;-) 这似乎是最简单的......
    • 啊,我刚刚发现我不能像 Shnugo 那样将其标记为答案,猜想最多只有一个答案是有意义的。我不确定现在该给谁打勾,因为两个答案都有我猜想是使用联合的正确方法,但我认为我应该将其保留为 Shnugo 的,因为我将使用最小答案 - 是正确的方法是什么?抱歉,我不确定这里的协议。无论如何,@mike123 也非常感谢您的快速回复:)
    • @dan0001 - Shnugo 帮我解答了。他值得称赞:)
    • 该方法适用于问题中的简单情况,但不适用于任意对象的数组。
    【解决方案3】:

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

    SELECT CONCAT(STUFF(@json1,LEN(@json1),1,','),STUFF(@json2,1,1,''))
    

    【讨论】:

      【解决方案4】:

      以下扩展了以前的解决方案,以适用于任意对象/数组/值的 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']'
          )
      

      【讨论】:

        猜你喜欢
        • 2018-05-29
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-12
        相关资源
        最近更新 更多