Sql 通过oracle 18中的json_表解析json
有一个请求,例如:Sql 通过oracle 18中的json_表解析json,sql,json,oracle,parsing,oracle18c,Sql,Json,Oracle,Parsing,Oracle18c,有一个请求,例如: with j (sJson) as ( select '{ "ID":"1444284517", "ID_ORD":"4255;2187606199", "Vals":{ "CODE":"ONB2B3BB8", "DORD&qu
with j (sJson) as (
select '{
"ID":"1444284517",
"ID_ORD":"4255;2187606199",
"Vals":{
"CODE":"ONB2B3BB8",
"DORD":"25.04.2021"
}
}'
from dual
)
select jt.*
from j
cross apply json_table (j.sJson, '$'
columns
ID varchar2(32) path '$.ID',
ID_ORD varchar2(32) path '$.ID_ORD',
nested path '$.Vals[*]'
columns (
CODE varchar2(9) path '$.CODE',
DORD varchar2(30) path '$.DORD',
....
)) jt
列中可能有不同的字段。
如何在不指定类型和路径的情况下列出列中的所有字段?这就是如何使其成为动态解析器?需要放弃代码varchar29路径“$.CODE”
我期望这一结果:
| ID | ID_ORD | CODE | DORD |
+------------+-----------------+-----------+------------+
| 1444284517 | 4255;2187606199 | ONB2B3BB8 | 25.04.2021 |
您可以定义以下功能: 创建函数get_键 CLOB中的值 返回SYS.ODCIVARCHAR2LIST管道化 是 js JSON_OBJECT_T:=JSON_OBJECT_T值; 密钥列表; 开始 keys:=js.get\u keys; 因为我在1。。键数循环 管排键; 端环; 终止 / 创建函数get_值 以CLOB表示的值, VARCHAR2中的路径 返回VARCHAR2 是 js JSON_OBJECT_T:=JSON_OBJECT_T值; 开始 返回js.get_字符串路径; 终止 / 然后使用查询: 以j sJson为例 选择'{ ID:1444284517, 识别号:4255;2187606199, VAL:{ 代码:ONB2B3BB8, DORD:2021年4月25日 } }' 来自双重 选择jt.id, 联合特遣部队司令部, k、 列_值作为键, 获取_值jt.vals,k.列_值作为值 来自j 交叉应用JSON_表 j、 sjson, '$' 柱 id VARCHAR220路径“$.id”, id_ord VARCHAR230路径“$.id_ord”, VAL VARCHAR24000格式JSON路径“$.VAL” jt 交叉应用获取键jt.vals k 哪些产出: 身份证件 身份证 钥匙 价值 1444284517 4255;2187606199 密码 ONB2B3BB8 1444284517 4255;2187606199 多德 25.04.2021
如果您确实需要可变数量的列,那么您需要对基于列的结果(如@MTO的答案)进行动态透视,或者生成动态json_表 您可以使用json_dataguide为特定的VAL数组生成模式,然后通过它自己的json_表和循环来生成columns子句名称、类型和路径 本例重新生成原始查询,只是它对JSON字符串使用了绑定变量,而不是CTE;然后使用数据指南中使用的相同字符串打开
create or replace function dynamic_parse(sJson clob)
return sys_refcursor as
sGuide clob;
sSQL clob;
rc sys_refcursor;
begin
-- initial static part of query
sSQL := q'^select jt.*
from json_table (:sJson, '$'
columns
ID varchar2(32) path '$.ID',
ID_ORD varchar2(32) path '$.ID_ORD',
nested path '$.Vals[*]'
columns (^';
select json_dataguide(jt.vals)
into sGuide
from json_table (sJson, '$'
columns
VALS clob format json path '$.Vals'
) jt;
for r in (
select jt.*
from json_table (sGuide format json, '$[*]'
columns
indx for ordinality,
path varchar2(30) path '$."o:path"',
type varchar2(30) path '$.type',
length number path '$."o:length"'
) jt
)
loop
sSQL := sSQL || case when r.indx > 1 then ',' end
|| chr(10) || ' '
|| '"' || substr(r.path, 3) || '"'
-- may need to handle other data type more carefully too
|| ' ' || case when r.type = 'string' then 'varchar2(' || r.length || ')' else r.type end
|| q'^ path '^' || r.path || q'^'^';
end loop;
-- final static part of query
sSQL := sSQL || chr(10) || ' )) jt';
dbms_output.put_line(sSQL);
open rc for sSQL using sJson;
return rc;
end;
/
显示一些步骤、生成的动态SQL语句,以及如何使用该语句打开ref游标。生成的动态语句如下所示:
select jt.*
from json_table (:sJson, '$'
columns
ID varchar2(32) path '$.ID',
ID_ORD varchar2(32) path '$.ID_ORD',
nested path '$.Vals[*]'
columns (
"CODE" varchar2(16) path '$.CODE',
"DORD" varchar2(16) path '$.DORD'
)) jt
它还显示了一个伪匿名块,该块调用函数并打印ref cursor内容,因为dbfiddle不支持select func_从dual返回ref cursor,您可以在SQL Developer中执行以下操作:
1444284517:4255;2187606199:ONB2B3BB8:25.04.2021
。。。但这说明了这种方法的一个问题:调用者必须事先知道列的数量和类型,或者本身必须使用一些动态处理元素
您可能还想探索更广泛的功能。SQL/JSON函数JSON\u表将特定的JSON数据投影到各种SQL数据类型的列中。您可以使用它将JSON文档的一部分映射到一个新的虚拟表的行和列中,您也可以将其视为一个内联视图 因为您的目标似乎是:通过json_表解析json。我建议阅读JSON数据指南功能。。Eg您可以基于行的结构创建视图,DBMS_JSON包将为您创建SQL/JSON。不需要编码。还可以将虚拟列添加到原始表中 使用文档创建一个表, 我添加了一个新字段XARR,以显示JSON数据指南特性的强大功能
drop table test_json;
create table test_json
as
with j (sJson ) as (
select CAST ('{
"ID":"1444284517",
"ID_ORD":"4255;2187606199",
"Vals":{
"CODE":"ONB2B3BB8",
"DORD":"25.04.2021",
"XARR":[{"IDARR":1},{"IDARR":2},{"IDARR":3}]
}
}' as VARCHAR2(2000))
from dual
)
select *
from j;
在文档顶部创建一个视图,
请编辑您的问题,以显示您希望从该示例中获得的输出;根据您所说的动态,一个不同的示例及其预期的输出。@AlexPoole,我改变了问题,列{}中的字段数量可能不确定。在执行查询之前,必须知道输出列的数量,所以我认为静态SQL不可能做到这一点。它在概念上类似于具有未知列数的枢轴。动态SQL必须通过解析JSON来构建columns子句,这似乎有点痛苦。
SELECT json_dataguide(SJSON, DBMS_JSON.FORMAT_HIERARCHICAL, DBMS_JSON.PRETTY)
FROM TEST_JSON;
drop view MYVIEW;
DECLARE
dg CLOB;
BEGIN
SELECT json_dataguide(SJSON, DBMS_JSON.FORMAT_HIERARCHICAL, DBMS_JSON.PRETTY)
INTO dg
FROM TEST_JSON where rownum < 2;
DBMS_JSON.create_view('MYVIEW',
'TEST_JSON',
'SJSON',
dg);
END;
/
select text from all_views where view_name = 'MYVIEW';
TEXT
-------------------------------------------------------------------
SELECT RT."SJSON",JT."ID",JT."CODE",JT."DORD",JT."ID_ORD",JT."IDARR"
FROM "ADMIN"."TEST_JSON" RT,
JSON_TABLE("SJSON", '$[*]' COLUMNS
"ID" varchar2(16) path '$.ID',
"CODE" varchar2(16) path '$.Vals.CODE',
"DORD" varchar2(16) path '$.Vals.DORD',
NESTED PATH '$.Vals.XARR[*]' COLUMNS (
"IDARR" number path '$.IDARR'),
"ID_ORD" varchar2(16) path '$.ID_ORD')JT
select * from myview;
ID CODE DORD ID_ORD IDARR
---------- --------- ---------- --------------- ---
1444284517 ONB2B3BB8 25.04.2021 4255;2187606199 1
1444284517 ONB2B3BB8 25.04.2021 4255;2187606199 2
1444284517 ONB2B3BB8 25.04.2021 4255;2187606199 3