Is there a way to make this Oracle query more optimal? Ideally without selecting from the same JSON_TABLE twice.
SELECT to_dncl_verification(status_code => t.status,
d_valid_from => to_date(t.d_valid_from, 'yyyy-mm-dd'),
d_valid_to => to_date(t.d_valid_to, 'yyyy-mm-dd'),
category_list => CAST(
MULTISET (SELECT tc.category, CASE WHEN tc.allowed = 'true' THEN 1 ELSE 0 END
FROM JSON_TABLE(l_clob_response, '$'
COLUMNS NESTED PATH '$.categories[*]'
COLUMNS (category VARCHAR2(255) PATH '$.category',
allowed VARCHAR2(255) PATH '$.allowed')
) tc
) AS tc_dncl_category
)
)
INTO y_verification_result
FROM JSON_TABLE(l_clob_response, '$'
COLUMNS status VARCHAR2(255) PATH '$.status',
d_valid_from VARCHAR2(255) PATH '$.dateValidFrom',
d_valid_to VARCHAR2(255) PATH '$.dateValidTo'
) t;
Let’s consider that types are created as follows:
create or replace type to_dncl_category is object (
category_code varchar2(20),
is_allowed number
);
create or replace type tc_dncl_category is table of to_dncl_category;
create or replace type to_dncl_verification is object (
status_code varchar2(20),
d_valid_from date,
d_valid_to date,
category_list tc_dncl_category
);
Also let’s consider variable l_clob_response is JSON with following data:
{
"id": "123",
"status": "PARTIALLY_BLOCKED",
"dateOfCheck": "2023-01-01",
"dateValidFrom": "2023-05-15",
"categories": [
{
"id": "123",
"category": "category ABC",
"allowed": true,
"dateCreated": "2023-05-05T10:47:19.745Z",
"recordVersion": 0
},
{
"id": "123",
"category": "category DEF",
"allowed": false,
"dateCreated": "2023-05-05T10:47:19.745Z",
"recordVersion": 0
},
{
"id": "123",
"category": "category GHI",
"allowed": true,
"dateCreated": "2023-05-05T10:47:19.745Z",
"recordVersion": 0
}
],
"dateValidTo": "2023-05-30",
"recordVersion": 0
}
My query works and returns an expected result, I just feel like it could be more optimal.
2
Answers
One variant is to extract the
categories
array in the outer query and then use that in the inner query. You would need to test each version and check which is more performant.fiddle
Oracle has default JSON to Object deserialization recursively based on the matched names. See 18.3 Using JSON_VALUE To Instantiate a User-Defined Object Type Instance section of
JSON_VALUE
function dosc for details.In order to map your JSON data to your object type you have to reshape the JSON document with, for example,
JSON_TRANSFORM
function:boolean
JSON datatype is mapped tovarchar2
orclob
, you need to either replacetrue/false
with1/0
(which I didn’t manage to work withset
modification) or usevarchar2
object attribute for this.Combining all together, there’s a query:
db<>fiddle