将动态 JSON 解析为 Oracle 表
Posted
技术标签:
【中文标题】将动态 JSON 解析为 Oracle 表【英文标题】:Parsing dynamic JSON into Oracle table 【发布时间】:2019-12-05 15:55:10 【问题描述】:我有一个带有这样一个表的 Oracle 12c 数据库
(
MSISDN VARCHAR2(15 BYTE),
DOCUMENT VARCHAR2(15 BYTE),
LOAD_DATE DATE,
LIST_NAME VARCHAR2(40 BYTE),
ATRIB VARCHAR2(40 BYTE),
VALUE VARCHAR2(200 BYTE)
)
另一方面,我有这个 JSON,其中包含该表的数据
"DigitalClient":
"documentNumber":"99999999-R",
"documentType":"PASSPORT",
"lastLineDate":123213213213,
"lastClientDate":123213213213,
"segment":"EMPRESA"
,
"ADSL":
"idOrder":216668542,
"status":"COMPLETED",
"orderType":"STANDARD",
"documentNumber":"161893223R",
"technologyAccess":"FTTVULA",
"dUserLastModifiedDate":1571329345000,
"type":"PERSON"
想法是这样解析表格中的这些信息:
MSISDN DOCUMENT LOAD_DATE LIST_NAME ATRIB VALUE
------ --------- ----------- ------------ -------- -----
911231231 6745671A 05/12/19 DigitalClient documentNumber 99999999R
911231231 6745671A 05/12/19 DigitalClient documentType PASSPORT
911231231 6745671A 05/12/19 ADSL idOrder 216668542
...
前三个字段是在JSON文件之外获取的,JSON文件相关字段是后三个。可以看到,字段 LIST_NAME 填充的是一级名称,而 ATRIB 和 VALUE 字段填充的是二级名称和值
现在,最困难的部分。 JSON 结构每天都在变化。我不知道 JSON 文件包含什么,既不知道一级或二级字段名称,也不知道有多少结构。我唯一知道的是该文件只有两层深:第一层是属性列表的名称,第二层是每个列表的属性及其值。
有人知道实现这一目标的好方法吗?我尝试了showed here 的解决方案,但不是我想要的,因为我必须在第一列中使用 SUBSTR 提取 LIST_NAME 和 ATRIB 信息,并且对于加载大量记录不是很有效。
提前致谢!
【问题讨论】:
检查这里,这可能会有所帮助:blogs.oracle.com/apex/tips-for-parsing-json-in-apex 感谢您的建议,但首先我将尝试使用 Oracle 12c 的原生 JSON 包 【参考方案1】:如果您使用的是 12.2,则可以使用 JSON Data Guide 为您创建视图:
create table t (
jdata varchar2(1000)
check ( jdata is json )
);
create search index ji
on t ( jdata )
for json
parameters ( 'sync (on commit)' );
insert into t values ('
"DigitalClient":
"documentNumber":"99999999-R",
"documentType":"PASSPORT",
"lastLineDate":123213213213,
"lastClientDate":123213213213,
"segment":"EMPRESA"
,
"ADSL":
"idOrder":216668542,
"status":"COMPLETED",
"orderType":"STANDARD",
"documentNumber":"161893223R",
"technologyAccess":"FTTVULA",
"dUserLastModifiedDate":1571329345000,
"type":"PERSON"
');
commit;
begin
dbms_json.create_view_on_path (
'vw', 't', 'jdata', '$'
);
end;
/
select * from vw;
JDATA$type JDATA$status JDATA$idOrder JDATA$orderType JDATA$documentNumber JDATA$technologyAccess JDATA$dUserLastModifiedDate JDATA$segment JDATA$documentType JDATA$lastLineDate JDATA$documentNumber_1 JDATA$lastClientDate
PERSON COMPLETED 216668542 STANDARD 161893223R FTTVULA 1571329345000 EMPRESA PASSPORT 123213213213 99999999-R 123213213213
请注意,您需要 is json
约束和搜索索引才能使其工作。
如果 JSON 包含一个数组,您将在输出中为每个元素获得一行。
例如:
insert into t values ( ' "aDifferent" : ["array", "of", "stuff"] ' );
commit;
begin
dbms_json.create_view_on_path (
'vw', 't', 'jdata', '$'
);
end;
/
select * from vw;
JDATA$type JDATA$status JDATA$idOrder JDATA$orderType JDATA$documentNumber JDATA$technologyAccess JDATA$dUserLastModifiedDate JDATA$segment JDATA$documentType JDATA$lastLineDate JDATA$documentNumber_1 JDATA$lastClientDate JDATA$string
PERSON COMPLETED 216668542 STANDARD 161893223R FTTVULA 1571329345000 EMPRESA PASSPORT 123213213213 99999999-R 123213213213 <null>
<null> <null> <null> <null> <null> <null> <null> <null> <null> <null> <null> <null> array
<null> <null> <null> <null> <null> <null> <null> <null> <null> <null> <null> <null> of
<null> <null> <null> <null> <null> <null> <null> <null> <null> <null> <null> <null> stuff
如果 JSON 文档中的属性名称发生变化,那么您将不断在视图中获取新列。因此,您可能希望在创建它之前删除它。
【讨论】:
嗨,克里斯,感谢您的回答。我正在尝试您的解决方案,当我尝试创建视图时,我遇到了这个错误(我的数据库是西班牙语,对此感到抱歉) ORA-06502: PL/SQL: error : error de conversión de carácter a número numérico o de valor ORA-06512: en "SYS.DBMS_JSON0", línea 24 ORA-06512: en "XDB.DBMS_JSON", línea 1000 ORA-06512: en línea 1 另外,我有一个疑问,你建议我如何获得“列表名称”信息?虚拟列名称不引用它:JDATA$documentNumber 可以属于 DigitalClient 或 ADSL 列表,我怎么知道这 2 个列表中的哪一个是正确的?谢了! 不知道为什么你会得到这个错误 - 请发布一个新问题,说明你是如何到达这个的(创建表 + 插入 + dbms_json 调用) 如果您知道要获取哪个对象的属性,您可以在该路径上创建一个视图,例如dbms_json.create_view_on_path ( 'vw', 't', 'jdata', '$.ADSL' );
。您也可以使用select json_dataguide ( jdata ) from t;
检查结构
我在本地测试数据库中逐步按照您的示例进行操作时遇到此错误。可能是配置问题?
关于您的第二条评论,问题是我不知道对象名称,因为 JSON 不是固定的,它具有可变数量的信息和对象属性结构。这就是我发疯的原因:-)以上是关于将动态 JSON 解析为 Oracle 表的主要内容,如果未能解决你的问题,请参考以下文章