我的pl / sql程序中有以下代码,它试图收集1700万行,并且在尝试分配16328字节时失败并出现错误ORA-04030:进程内存(koh-kghu调用,pmuccst:风干吨/记录)
TYPE rc_test IS RECORD(
ROWID VARCHAR2(200),
contact_id VARCHAR2(200),
last_name VARCHAR2(200),
first_name VARCHAR2(200),
phone VARCHAR2(200),
email VARCHAR2(200),
birth_day date,
address_id VARCHAR2(200),
seq NUMBER,
NEWID NUMBER);
TYPE rctype
IS TABLE OF RC_TEST;
rcrecords RCTYPE;
BEGIN
SELECT ROWID,
contact_id,
last_name,
first_name,
phone,
email,
birth_day,
address_id,
seq,
NEWID
bulk collect INTO rcrecords
FROM HR.TMP_TBL_SEQ a
order by last_name, first_name, seq;
FOR i IN 1..rcrecords.count LOOP
- <<>> END LOOP;
它可以运行数百或数千行的样本数据,但不能用于数百万行。
我已阅读此错误的故障排除但其中大多数都是围绕通过DBA完成此操作,DBA将执行某些调整或建议我们增加可能解决问题的RAM但由于首先我确实想要的某些限制改变代码本身的逻辑。
有没有更好的方法来改善上述类型代码中的逻辑以摆脱内存不足错误?
代替我的代码中使用的表记录,任何人都可以提供替代代码吗?
非常感谢。
答案 0 :(得分:0)
您可以将BULK COLLECT
与LIMIT
子句(http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html)一起使用。在您的情况下,它看起来类似于:
CURSOR cur1 IS
SELECT ROWID, contact_id, last_name, first_name,
phone, email, birth_day, address_id, seq,
NEWID FROM HR.TMP_TBL_SEQ a order by last_name, first_name, seq;
TYPE T_TEST IS TABLE OF cur1 %ROWTYPE INDEX BY PLS_INTEGER;;
test_data T_TEST;
BEGIN
OPEN cur1;
LOOP
FETCH cur1
BULK COLLECT INTO test_data LIMIT 10000;
FOR indx IN 1 .. test_data.COUNT
LOOP
NULL;
--- process data
END LOOP;
EXIT WHEN test_data.COUNT < 10000;
END LOOP;
CLOSE cur1;
答案 1 :(得分:0)
使用LIMIT子句避免对BULK COLLECT进行这种“无限制”使用。 将SELECT语句移动到显式游标声明中,然后使用简单循环从表中获取许多但不是所有行,每次执行循环体时都使用可选的LIMIT子句。
有关示例和解释,请参阅此oracle技术问题,请参阅http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html
答案 2 :(得分:0)
用游标for-loop替换BULK COLLECT
:
begin
for rcrecords in
(
SELECT ROWID,
contact_id,
last_name,
first_name,
phone,
email,
birth_day,
address_id,
seq,
NEWID
bulk collect INTO rcrecords
FROM HR.TMP_TBL_SEQ a
order by last_name, first_name, seq
) loop
--Process data.
null;
end loop;
end;
/
Oracle将自动负责批量收集,限制和声明数据类型。