Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Dołącz lub dołącz obiekt json wewnątrz innego obiektu json obiektu json za pomocą plsql

Jeśli masz przykładowe dane (przechowywane jako 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"
    }
  ]
}'
);
 

Następnie możesz użyć JSON_MERGEPATCH aby do nich dołączyć (jeśli najpierw agregujesz istniejące i nowe wartości):

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;
 

Które wyjścia:

db<>fiddle tutaj

Aktualizacja

Jeśli używasz BLOB kolumna to możesz użyć dokładnie tego samego kodu. Jeśli chcesz go użyć w UPDATE lub INSERT oświadczenie, będziesz potrzebować sposobu na przekonwertowanie CLOB dane wyjściowe z JSON_MERGEPATCH do BLOB . Nie używaj UTL_RAW.CAST_TO_RAW ponieważ nie powiedzie się, jeśli długość JSON jest większa niż 4000 znaków; zamiast tego możesz użyć funkcji:

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;
/
 

Następnie, jeśli masz tabelę i przykładowe dane:

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"
    }
  ]
}'
  )
);
 

Następnie, aby zaktualizować kolumnę o dodatkowe wartości, możesz użyć:

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 tutaj




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. jak wybrać tylko wiersz z sekwencją max bez użycia podzapytania?

  2. Wybierz odrębne ... sprzężenie wewnętrzne vs. Wybierz ... gdzie id w (...)

  3. Tworzenie indeksu przestrzennego na oracle

  4. Scal zakresy dat

  5. Powrót do monitu sqlplus