Si vous disposez des exemples de données (stockés sous forme de 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"
}
]
}'
);
Ensuite, vous pouvez utiliser JSON_MERGEPATCH
pour les rejoindre (si vous agrégez d'abord les valeurs existantes et nouvelles) :
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;
Qui sort :
db<>violon ici
Mettre à jour
Si vous utilisez un BLOB
colonne, vous pouvez utiliser exactement le même code. Si vous souhaitez l'utiliser dans une UPDATE
ou INSERT
alors vous aurez besoin d'un moyen de convertir le CLOB
sortie de JSON_MERGEPATCH
à un BLOB
. Ne pas utiliser UTL_RAW.CAST_TO_RAW
car il échouera si la longueur du JSON est supérieure à 4000 caractères ; à la place, vous pouvez utiliser la fonction :
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;
/
Ensuite, si vous disposez du tableau et des exemples de données :
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"
}
]
}'
)
);
Ensuite, pour mettre à jour la colonne avec les valeurs supplémentaires, vous pouvez utiliser :
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<>violon ici