sql >> データベース >  >> RDS >> Oracle

plsqlを使用して別のjsonオブジェクトjsonオブジェクト内にjsonオブジェクトを追加またはアタッチします

    サンプルデータ(CLOBとして保存されている)がある場合 ):

    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_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_MERGEPATCH(
             department_data,
             (
               SELECT JSON_OBJECT(
                        KEY 'employees'
                        VALUE JSON_ARRAYAGG( json FORMAT JSON RETURNING CLOB )
                        FORMAT JSON
                      )
               FROM   employees
             )
             RETURNING CLOB PRETTY
           ) AS merged
    FROM   departments_json
    WHERE  department_id = 110;
    

    どの出力:

    db <> fiddle こちら

    更新

    BLOBを使用している場合 列の場合、まったく同じコードを使用できます。 UPDATEで使用したい場合 またはINSERT ステートメントの場合、CLOBを変換する方法が必要になります JSON_MERGEPATCHからの出力 BLOBに 。 UTL_RAW.CAST_TO_RAWは使用しないでください JSONの長さが4000文字を超えると失敗するため、代わりに、次の関数を使用できます:

    CREATE FUNCTION clob_to_blob(
      value            IN CLOB,
      charset_id       IN INTEGER DEFAULT DBMS_LOB.DEFAULT_CSID,
      error_on_warning IN NUMBER  DEFAULT 0
    ) RETURN BLOB
    IS
      result       BLOB;
      dest_offset  INTEGER := 1;
      src_offset   INTEGER := 1;
      lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
      warning      INTEGER;
      warning_msg  VARCHAR2(50);
    BEGIN
      DBMS_LOB.CreateTemporary(
        lob_loc => result,
        cache   => TRUE
      );
    
      DBMS_LOB.CONVERTTOBLOB(
        dest_lob     => result,
        src_clob     => value,
        amount       => LENGTH( value ),
        dest_offset  => dest_offset,
        src_offset   => src_offset,
        blob_csid    => charset_id,
        lang_context => lang_context,
        warning      => warning
      );
      
      IF warning != DBMS_LOB.NO_WARNING THEN
        IF warning = DBMS_LOB.WARN_INCONVERTIBLE_CHAR THEN
          warning_msg := 'Warning: Inconvertible character.';
        ELSE
          warning_msg := 'Warning: (' || warning || ') during CLOB conversion.';
        END IF;
        
        IF error_on_warning = 0 THEN
          DBMS_OUTPUT.PUT_LINE( warning_msg );
        ELSE
          RAISE_APPLICATION_ERROR(
            -20567, -- random value between -20000 and -20999
            warning_msg
          );
        END IF;
      END IF;
    
      RETURN result;
    END clob_to_blob;
    /
    

    次に、テーブルとサンプルデータがある場合:

    create table departments_json (
      department_id
        integer
        NOT NULL
        CONSTRAINT departments_json__id__pk PRIMARY KEY,
      department_data
        BLOB
        NOT NULL
        CONSTRAINT departments_json__data__chk CHECK ( department_data IS JSON )
    );
    
    insert into departments_json 
    json values (
      110,
      CLOB_TO_BLOB(
    '{
      "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"
        }
      ]
    }'
      )
    );
    

    次に、追加の値で列を更新するには、次を使用できます。

    UPDATE departments_json
    SET department_data = CLOB_TO_BLOB( JSON_MERGEPATCH(
             department_data,
             (
               SELECT JSON_OBJECT(
                        KEY 'employees'
                        VALUE JSON_ARRAYAGG( json FORMAT JSON RETURNING CLOB )
                        FORMAT JSON
                      )
               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 PRETTY
           ) )
    WHERE  department_id = 110;
    

    db <> fiddle こちら




    1. 空間mysqlインデックスに結合します

    2. これがSQLで可能かどうかを知る必要があります

    3. 生年月日と今日からのOracleAgeの計算

    4. MySQLの一意のIDまたは結合されたID