Se você tiver os dados de amostra (armazenados como um
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"
}
]
}'
);
Então você pode usar
JSON_MERGEPATCH
para juntá-los (se você agregar os valores existentes e novos primeiro):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;
Quais saídas:
db<>fiddle aqui
Atualizar
Se você estiver usando um
BLOB
coluna, então você pode usar exatamente o mesmo código. Se você quiser usá-lo em um UPDATE
ou INSERT
então você precisará de uma maneira de converter o CLOB
saída de JSON_MERGEPATCH
para um BLOB
. Não use UTL_RAW.CAST_TO_RAW
pois falhará se o comprimento do JSON for maior que 4000 caracteres; em vez disso, você pode usar a função: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;
/
Então, se você tiver a tabela e os dados de amostra:
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"
}
]
}'
)
);
Então, para atualizar a coluna com os valores adicionais, você pode 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 aqui