让我解释一下我的设想,这样你可能会更好地理解我的问题。我们需要从一组具有特定格式的表中创建一个json文件。我有使用apexèujson的想法,因为它非常简单,但是我有一个内存问题,因为json文档生成了500万条记录。实际上,当我通过应用rownum过滤器来减少记录数时,这个过程就起作用了。但是,当查询尝试创建记录总数为的json时,我得到了一个plsql数值错误,其背后基本上是内存溢出。
我最初的json查询如下:
DECLARE
l_cursor SYS_REFCURSOR;
BEGIN
for l_hdr_row in (select FILENAME, REPORT_DATE, DOMAINCODE, LEGALENTITYCODE from RDM_OUT.JSON_NKEY_REP_HDR where DOMAINCODE = '00001')
loop
APEX_JSON.INITIALIZE_CLOB_OUTPUT;
APEX_JSON.OPEN_OBJECT;
APEX_JSON.OPEN_OBJECT(l_hdr_row.FILENAME);
APEX_JSON.OPEN_OBJECT;
APEX_JSON.WRITE('Date',l_hdr_row.REPORT_DATE);
APEX_JSON.WRITE('DomainCode',l_hdr_row.DOMAINCODE);
APEX_JSON.WRITE('LegalEntityCode',l_hdr_row.LEGALENTITYCODE);
APEX_JSON.OPEN_ARRAY('Keys');
FOR dtl IN (SELECT NATIVEKEY, MASTERKEY, ENDDATE
FROM RDM_OUT.JSON_NKEY_REP_DTL DTL
WHERE DTL.FILENAME = l_hdr_row.FILENAME) LOOP
APEX_JSON.OPEN_OBJECT;
APEX_JSON.WRITE('NativeKey',dtl.NATIVEKEY);
APEX_JSON.WRITE('MasterKey',dtl.MASTERKEY);
APEX_JSON.WRITE('EndDate',dtl.ENDDATE);
APEX_JSON.CLOSE_OBJECT;
END LOOP;
APEX_JSON.CLOSE_ARRAY;
APEX_JSON.CLOSE_OBJECT;
APEX_JSON.CLOSE_ALL;
DBMS_OUTPUT.PUT_LINE(APEX_JSON.GET_CLOB_OUTPUT);
APEX_JSON.FREE_OUTPUT;
end loop;
END;
/
第一个循环实际上只恢复一行,这在第二个循环中处理,我得到了第一个循环中第一个也是唯一一个循环中出现的550万条记录。我试着使用json_对象和json_数组,但是我不能得到apex_json给我的输出格式。
我使用的是oracle12.2,因此我不能像18c和19c中的一些json函数那样进行改进。
让我向您展示我使用apex\ujson的原始查询的内容
SQL> set serveroutput on size unlimited echo on timing on
SQL> DECLARE
2 l_cursor SYS_REFCURSOR;
BEGIN
3 4
5 for l_hdr_row in (select FILENAME, REPORT_DATE, DOMAINCODE, LEGALENTITYCODE from RDM_OUT.JSON_NKEY_REP_HDR where DOMAINCODE = '00001')
loop
6 7 8 APEX_JSON.INITIALIZE_CLOB_OUTPUT;
9 APEX_JSON.OPEN_OBJECT;
10 APEX_JSON.OPEN_OBJECT(l_hdr_row.FILENAME);
11
APEX_JSON.OPEN_OBJECT;
12 13 APEX_JSON.WRITE('Date',l_hdr_row.REPORT_DATE);
APEX_JSON.WRITE('DomainCode',l_hdr_row.DOMAINCODE);
14 15 APEX_JSON.WRITE('LegalEntityCode',l_hdr_row.LEGALENTITYCODE);
APEX_JSON.OPEN_ARRAY('Keys');
16 17
FOR dtl IN (SELECT NATIVEKEY, MASTERKEY, ENDDATE
FROM RDM_OUT.JSON_NKEY_REP_DTL DTL
18 19 20 WHERE DTL.FILENAME = l_hdr_row.FILENAME and rownum < 5 ) LOOP
APEX_JSON.OPEN_OBJECT;
APEX_JSON.WRITE('NativeKey',dtl.NATIVEKEY);
21 22 23 24 APEX_JSON.WRITE('MasterKey',dtl.MASTERKEY);
APEX_JSON.WRITE('EndDate',dtl.ENDDATE);
25 APEX_JSON.CLOSE_OBJECT;
END LOOP;
26 27 28 APEX_JSON.CLOSE_ARRAY;
APEX_JSON.CLOSE_OBJECT;
APEX_JSON.CLOSE_ALL;
29 30 31 32 DBMS_OUTPUT.PUT_LINE(APEX_JSON.GET_CLOB_OUTPUT);
APEX_JSON.FREE_OUTPUT;
end loop;
END;
33 34 35 36 /
{
"RTTA_00013_20190831_00001_00055_NKEY":{
{
"Date":"2019-08-31"
,"DomainCode":"
00001"
,"LegalEntityCode":"00055"
,"Keys":[
{
"NativeKey":"85430299"
,"MasterKey
":"01483175470"
,"EndDate":"9999-12-31"
}
,{
"NativeKey":"33227843"
,"MasterKey"
:"329401533000001934"
,"EndDate":"9999-12-31"
}
,{
"NativeKey":"42565570"
,"Mast
erKey":"01500329780"
,"EndDate":"9999-12-31"
}
,{
"NativeKey":"98536882"
,"Maste
rKey":"01502416501"
,"EndDate":"9999-12-31"
}
]
}
}
}
我的问题如下:
有没有更好的方法来做我正在做的事?也许我可以用批量收集与限制吗?
如何使用json\u对象和json\u数组获得相同的结果和格式?我试过了,但是我没有得到相同的输出格式。
谢谢大家!
1条答案
按热度按时间bt1cpqcv1#
最后,我想出了我自己的解决办法。我改为批量收集,现在的过程完美地工作。在这里您可以看到代码现在的样子:
我无法使用sql/json函数获得相同的格式,所以我决定转换所使用的代码以获得bulk collect的好处。我还修改了在输出中打印clob的方式,以避免缓冲区出现问题:
我想一定有一个使用sql/json的选项,但我相信apex\ujson提供了一个非常简单的api。要小心内存溢出或性能问题,批量收集可能是一个好方法。