Si tiene los datos de muestra (almacenados como 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"
}
]
}'
);
Entonces puedes usar JSON_MERGEPATCH
para unirlos (si agrega primero los valores existentes y nuevos):
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;
Qué salidas:
db<>fiddle aquí
Actualizar
Si está utilizando un BLOB
columna, entonces puede usar exactamente el mismo código. Si quieres usarlo en un UPDATE
o INSERT
entonces necesitará una forma de convertir el CLOB
salida de JSON_MERGEPATCH
a un BLOB
. No use UTL_RAW.CAST_TO_RAW
ya que fallará si la longitud del JSON es mayor a 4000 caracteres; en su lugar, puede utilizar la función:
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;
/
Luego, si tiene la tabla y los datos de muestra:
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"
}
]
}'
)
);
Luego, para actualizar la columna con los valores adicionales, puede usar:
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 aquí