问题
I am trying to parse JSON using JSON_TABLE.
Oracle DB version 12.1.0.2
{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{
"mName" : "Carol",
"lName" : "Cena"
},
{
"mName" : "Mark",
"lName" : "Karlo"
}
]
}
Tried with below query but not getting expected result.
select * from json_Table(
'{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{"mName" : "Carol","lName" : "Cena"},
{"mName" : "Mark","lName" : "Karlo"}
]
}',
'$' columns ( rownr number path '$.Rownum',
name varchar2(100) path '$.Name',
nested path '$.TextObj[*]' columns (mName varchar2(100) path '$.mName',
lName varchar2(100) path '$.lName'
),
nested path '$.AddressArray[*]' columns(AddressArray varchar2(100) path '$')
)
);
Output from above query:
Expected output:
回答1:
You seem to want a cross join of the array values (grouped by rownum and name). This is not a standard JSON structure, so you shouldn't expect to be able to do this with a single application of json_table.
Here is one way to do this with two calls to json_table. In the first call, you use a nested path to get just the names, but you still keep the address arrays. In a second call, you unpack the addresses, separately for each row produced by the first call.
Note the use of an optimizer hint in the outer select. This is needed, because without it the optimizer will try an illegal "unnesting" of the lateral join (outer apply) and then throw an error, instead of leaving the query as is. (This is a very common and annoying habit of the optimizer: it tries something that is invalid, and then it complains about it.)
Also, rownum is a reserved keyword - you can't use it as a column name in the output. (Technically you can, with additional work, but it is best to believe that you can't.)
with
t as (
select *
from json_Table(
'{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{"mName" : "Carol","lName" : "Cena"},
{"mName" : "Mark","lName" : "Karlo"}
]
}',
'$' columns (
rownr number path '$.Rownum',
name varchar2(100) path '$.Name',
addressArray varchar2(4000) format json path '$.AddressArray',
nested path '$.TextObj[*]'
columns (mName varchar2(100) path '$.mName',
lName varchar2(100) path '$.lName'
)
)
)
)
select /*+ no_query_transformation */ rownr, name, mname, lname, address
from t
outer apply
json_table (t.addressArray, '$[*]'
columns (address varchar2(10) path '$')
)
;
Output:
ROWNR NAME MNAME LNAME ADDRESS
----- ------ ------ ------ ----------
1 John Carol Cena Address1
1 John Carol Cena Address2
1 John Mark Karlo Address1
1 John Mark Karlo Address2
回答2:
You could chain several json_table calls:
select j1.rnum, j1.name, j2.address, j3.mName, j3.lName
from (
select '{
"Rownum": "1",
"Name": "John",
"AddressArray":["Address1", "Address2"],
"TextObj":[{
"mName" : "Carol",
"lName" : "Cena"
},
{
"mName" : "Mark",
"lName" : "Karlo"
}
]
}' as str
from dual
) t
outer apply json_table (
t.str format json, '$'
columns (
rNum number path '$.Rownum',
name varchar2(10) path '$.Name',
addressArray varchar2(4000) format json path '$.AddressArray',
textObj varchar2(4000) format json path '$.TextObj'
)
) j1
outer apply json_table (
j1.addressArray, '$[*]'
columns (
address varchar2(10) path '$'
)
) j2
outer apply json_table (
j1.textObj, '$[*]'
columns (
mName varchar2(10) path '$.mName',
lName varchar2(10) path '$.lName'
)
) j3
where t is just an inline view to supply your sample JSON as a str column, which is then processed by the first json_table. That gets the rownumber and name values, and also the address array which is passed to the second json_table, and the text object which is passed to the third json_table. Those produce the values from their arrays.
RNUM | NAME | ADDRESS | MNAME | LNAME
---: | :--- | :------- | :---- | :----
1 | John | Address1 | Carol | Cena
1 | John | Address1 | Mark | Karlo
1 | John | Address2 | Carol | Cena
1 | John | Address2 | Mark | Karlo
db<>fiddle (18c, but verified on 12cR1).
来源:https://stackoverflow.com/questions/66065792/parse-json-using-oracle-sql-json-table