Reputation: 1
I have a JSON document stored in myjson table, doc column.
{
"totalResultsCount": 19,
"geonames": [
{
"geonameId": 2593109,
"fcode": "ADM1"
},
{
"geonameId": 3336899,
"fcode": "ADM1"
}, ...
When I run the query,
select j.doc.geonames.geonameId from myjson j where j.doc.geonames.fcode like '%ADM1%';
I get an array of IDs.
[2593109,3336899,3114710,2521383,3336903,2593110,3336898,3336900,2593111,3336901,2519582,2593112,3336902,3336897,3117732,6362988,2513413,3115609,2593113]
How do I read this array and print each ID using a FOR LOOP?
Upvotes: 0
Views: 2711
Reputation: 65105
You can use JSON_TABLE()
function within Oracle's SQL containing a CROSS JOIN in order to parse individual column values for product
and fcode
, and use them in SELECT-list and WHERE condition, respectively as below :
SELECT ROW_NUMBER() OVER (ORDER BY 1) AS row_id, js.product
FROM myjson
CROSS JOIN
JSON_TABLE(
doc, '$.geonames[*]' COLUMNS (
product VARCHAR(100) PATH '$.geonameId',
fcode VARCHAR(100) PATH '$.fcode'
)
) js
WHERE js.fcode = 'ADM1'
Update : Evaluate the following depending on your comment of need for array assignment of the returning values :
SQL> SET SERVEROUTPUT ON
SQL> DECLARE
json_array_t OWA.VC_ARR;
BEGIN
FOR c IN
(
SELECT ROW_NUMBER() OVER (ORDER BY 1) - 1 AS row_id, js.product
FROM myjson
CROSS JOIN JSON_TABLE(
doc, '$.geonames[*]' COLUMNS (
product VARCHAR(100) PATH '$.geonameId',
fcode VARCHAR(100) PATH '$.fcode'
)
) js
WHERE js.fcode = 'ADM1' )
LOOP
json_array_t(c.row_id) := c.product;
DBMS_OUTPUT.PUT_LINE( 'value for json_array_t('||c.row_id||') is '||json_array_t(c.row_id) );
END LOOP;
END;
/
Update 2 : You can set array values by using your original query, and then extract all members of that array using a FOR LOOP as desired lastly :
DECLARE
l_str VARCHAR2(32767);
l_top_obj JSON_OBJECT_T;
l_dept_arr JSON_ARRAY_T;
l_dept_obj JSON_OBJECT_T;
l_emp_arr JSON_ARRAY_T;
l_emp_obj JSON_OBJECT_T;
BEGIN
SELECT j.doc
INTO l_str
FROM myjson j
WHERE j.doc.geonames.fcode LIKE '%ADM1%';
l_top_obj := JSON_OBJECT_T(l_str);
l_dept_arr := l_top_obj.get_array('geonames');
FOR i IN 0 .. l_dept_arr.get_size - 1
LOOP
l_dept_obj := TREAT(l_dept_arr.get(i) AS JSON_OBJECT_T);
DBMS_OUTPUT.PUT_LINE('index : '||i||' - geonameId : ' || l_dept_obj.get_number('geonameId'));
END LOOP;
END;
/
Upvotes: 1
Reputation: 3316
We can use JSON_TABLE for this purpose ,
SQL/JSON function json_table projects specific JSON data to columns of various SQL data types. You use it to map parts of a JSON document into the rows and columns of a new, virtual table, which you can also think of as an inline view.
WITH json AS
(SELECT '[2593109,3336899,3114710,2521383,3336903,2593110,3336898,3336900,2593111,3336901,2519582,2593112,3336902,3336897,3117732,6362988,2513413,3115609,2593113]' doc
FROM dual)
SELECT geonameId
FROM json_table((SELECT doc FROM json)
,'$[*]' columns(geonameId NUMBER path '$'))
Edit
Using JSON_TABLE
as source in for loop
begin
for i in (SELECT geonameid
FROM json_table('[2593109,3336899,3114710,2521383,3336903,2593110,3336898,3336900,2593111,3336901,2519582,2593112,3336902,3336897,3117732,6362988,2513413,3115609,2593113]'
,'$[*]' columns(geonameId NUMBER path '$')))
loop
dbms_output.put_line('Id: '||i.geonameid);
end loop;
end;
/
Again not sure if you want this.
Reference fiddle
Upvotes: 1