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