【问题标题】:Update a json column after use JSON_MERGEPATCH使用 JSON_MERGEPATCH 后更新 json 列
【发布时间】:2021-01-30 22:35:20
【问题描述】:

有这个

create table departments_json (
  department_id
    integer
    NOT NULL
    CONSTRAINT departments_json__id__pk PRIMARY KEY,
  department_data
    CLOB
    NOT NULL
    CONSTRAINT departments_json__data__chk CHECK ( department_data IS JSON )
);

insert into departments_json 
json values ( 110, '{
  "department": "Accounting",
  "employees": [
    {
      "name": "Higgins, Shelley",
      "job": "Accounting Manager",
      "hireDate": "2002-06-07T00:00:00"
    },
    {
      "name": "Gietz, William",
      "job": "Public Accountant",
      "hireDate": "2002-06-07T00:00:00"
    }
  ]
}'
);

还有新的 json :

{
  "employees": [
    {
      "name": "Chen, John",
      "job": "Accountant",
      "hireDate": "2005-09-28T00:00:00"
    },
    {
      "name": "Greenberg, Nancy",
      "job": "Finance Manager",
      "hireDate": "2002-08-17T00:00:00"
    },
    {
      "name": "Urman, Jose Manuel",
      "job": "Accountant",
      "hireDate": "2006-03-07T00:00:00"
    }
  ]
}

POST 之后,回复对我帮助很大。但现在是时候用新的 json 更新列部门数据了。我正在使用这个查询:

update departments_json d
set d.department_data = 
    WITH employees ( json ) AS (
      SELECT j.json
      FROM   departments_json d
             CROSS APPLY JSON_TABLE(
               d.department_data,
               '$.employees[*]'
               COLUMNS (
                 json CLOB FORMAT JSON PATH '$'
               )
             ) j
      WHERE  d.department_id = 110
    UNION ALL
      SELECT j.json
      FROM   JSON_TABLE(
               '{
      employees: [
        {
          name: Chen, John,
          job: Accountant,
          hireDate: 2005-09-28T00:00:00
        },
        {
          name: Greenberg, Nancy,
          job: Finance Manager,
          hireDate: 2002-08-17T00:00:00
        },
        {
          name: Urman, Jose Manuel,
          job: Accountant,
          hireDate: 2006-03-07T00:00:00
        }
      ]
    }',
               '$.employees[*]'
               COLUMNS (
                 json CLOB FORMAT JSON  PATH '$'
               )
             ) j
    )JSON_MERGEPATCH(
         d.department_data,
         (
           SELECT JSON_OBJECT(
                    KEY 'employees'
                    VALUE JSON_ARRAYAGG( json FORMAT JSON RETURNING CLOB )
                    FORMAT JSON
                  )
           FROM   employees
         )
       )
WHERE  d.department_id = 110;

但我得到了这个错误,我不知道哪里错了

错误:

Error en la línea de comandos : 3 Columna : 5
Informe de error -
Error SQL: ORA-00936: falta una expresión
00936. 00000 -  "missing expression"
*Cause:    
*Action:

怎么了,我按照这个步骤:LINK

注意:这是我的桌子的样子:

更新

应用 MP0 建议后,这就是我的查询的样子(两个选项)

但问题是我有这个错误:

ORA-40478: output value too large (maximum: 4000)

【问题讨论】:

    标签: sql json oracle oracle19c


    【解决方案1】:

    你可以使用:

    UPDATE departments_json
    SET department_data = JSON_MERGEPATCH(
             department_data,
             (
               SELECT JSON_OBJECT(
                        KEY 'employees'
                        VALUE JSON_ARRAYAGG( json FORMAT JSON RETURNING CLOB )
                        FORMAT JSON RETURNING CLOB
                      )
               FROM   (
      SELECT j.json
      FROM   departments_json d
             CROSS APPLY JSON_TABLE(
               d.department_data,
               '$.employees[*]'
               COLUMNS (
                 json CLOB FORMAT JSON PATH '$'
               )
             ) j
      WHERE  d.department_id = 110
    UNION ALL
      SELECT j.json
      FROM   JSON_TABLE(
               '{
      "employees": [
        {
          "name": "Chen, John",
          "job": "Accountant",
          "hireDate": "2005-09-28T00:00:00"
        },
        {
          "name": "Greenberg, Nancy",
          "job": "Finance Manager",
          "hireDate": "2002-08-17T00:00:00"
        },
        {
          "name": "Urman, Jose Manuel",
          "job": "Accountant",
          "hireDate": "2006-03-07T00:00:00"
        }
      ]
    }',
               '$.employees[*]'
               COLUMNS (
                 json CLOB FORMAT JSON  PATH '$'
               )
             ) j
               )
             )
             RETURNING CLOB
           )
    WHERE  department_id = 110;
    

    输出:

    DEPARTMENT_ID | DEPARTMENT_DATA ------------: | :------------------------------------------------ -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----- 110 | {"department":"Accounting","employees":[{"name":"Higgins, Shelley","job":"Accounting Manager","hireDate":"2002-06-07T00:00:00"} ,{"name":"Gietz, William","job":"Public Accountant","hireDate":"2002-06-07T00:00:00"},{"name":"Chen, John","工作":"会计","hireDate":"2005-09-28T00:00:00"},{"name":"Greenberg, Nancy","job":"财务经理","hireDate":"2002 -08-17T00:00:00"},{"name":"Urman, Jose Manuel","job":"Accountant","hireDate":"2006-03-07T00:00:00"}]}

    db小提琴here


    更新

    您的代码有几个问题:

    • JSON_MERGEPATCH 需要环绕WITH ... SELECT 语句,因为该语句的输出应该是JSON_MERGEPATCH 的第二个参数;和
    • 您的 JSON 无效,因为它缺少标识符和字符串周围的所有双引号。

    如果你解决了这个问题,那么你的代码也可以工作:

    update departments_json d
    set d.department_data = JSON_MERGEPATCH(
      d.department_data,
      ( -- Start of second argument of JSON_MERGEPATCH
        WITH employees ( json ) AS (
          SELECT j.json
          FROM   departments_json d
                 CROSS APPLY JSON_TABLE(
                   d.department_data,
                   '$.employees[*]'
                   COLUMNS (
                     json CLOB FORMAT JSON PATH '$'
                   )
                 ) j
          WHERE  d.department_id = 110
        UNION ALL
          SELECT j.json
          FROM   JSON_TABLE(
                   '{
          "employees": [
            {
              "name": "Chen, John",
              "job": "Accountant",
              "hireDate": "2005-09-28T00:00:00"
            },
            {
              "name": "Greenberg, Nancy",
              "job": "Finance Manager",
              "hireDate": "2002-08-17T00:00:00"
            },
            {
              "name": "Urman, Jose Manuel",
              "job": "Accountant",
              "hireDate": "2006-03-07T00:00:00"
            }
          ]
        }',
                   '$.employees[*]'
                   COLUMNS (
                     json CLOB FORMAT JSON  PATH '$'
                   )
                 ) j
        )
        SELECT JSON_OBJECT(
                 KEY 'employees'
                 VALUE JSON_ARRAYAGG( json FORMAT JSON RETURNING CLOB )
                 FORMAT JSON RETURNING CLOB
               )
        FROM   employees
      ) -- End of second argument of JSON_MERGEPATCH
      RETURNING CLOB
    )
    WHERE  d.department_id = 110;
    

    db小提琴here

    【讨论】:

    • 再次您好(我更新我的问题),请根据我的情况调整此代码,我收到此错误:Informe de error - ORA-40478: output value too large (最大:4000)。就我而言,我有第一个 json 有 1000 名员工,第二个 json 有 900 多名员工。如果我执行 UNION ALL 我会看到我所有的员工 (1900),但是当我使用更新部分执行时,它不起作用,可能是什么问题?问候
    • @Julio 字符串文字只能包含 4000 个字符。如果要传递超过 4000 个字符,则需要使用 CLOBBLOB(或将其拆分为小于 4000 个字符的块)。可能您只需要在JSON_OBJECT 函数调用的末尾添加RETURNING CLOB。如果不是这样,那么在您的代码中某处已达到此限制,您将需要调试您的代码以找出它在哪里。您可以获取部件(即休息请求、WITH ... SELECTUPDATE)并单独运行它们检查输入值,如果有任何失败。
    • 您好,如果您看到我的问题,我会使用两个选项上传第二张图片,并带有返回选项(clob),但错误是相同的。我必须存储大 json (1900) 员工,所以你有什么建议?问候
    • @Julio 尝试将第一个示例中最后一行的第 6 行(或第二个示例中的第 7 行)从 FORMAT JSON 更改为 FORMAT JSON RETURNING CLOB
    • 你是对的,它工作!非常感谢大家。 :)
    猜你喜欢
    • 2021-12-26
    • 1970-01-01
    • 2020-09-08
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2020-04-23
    相关资源
    最近更新 更多