我写了一个用于构建报告表的包。我正在测试的函数的简化代码如下:
function do_build return integer is
V_RESULT PLS_INTEGER := 0;
cursor all_entities is
select e.id_number
from entity e
;
BEGIN
c_count := 0; -- this variable is declared at the package level outside of this function
for rec in all_entities LOOP
BEGIN
insert into reporting (
select *
from table(get_report_data(rec.id_number))
);
c_count := c_count + 1;
if MOD(c_count, 1000) = 0 Then
-- record status to table
commit;
end if;
EXCEPTION
WHEN OTHERS THEN
-- record exception to table
END;
END LOOP;
return V_RESULT;
END;
一点背景:get_report_data是一个返回包含所有输入实体报告数据的数据集的函数。
"报告"大约有1000个记录中缺少100个记录。构建完成时的表。没有抛出异常,除了丢失的记录之外,一切似乎都成功了(函数返回0给调用者)。
当我为没有记录其报告数据的实体记录运行get_report_data时,记录显示正常。事实上,我可以做一个特别的"插入报告(select * from table(get_reporting_data(missing_id))"并且将插入信息。
为什么会跳过/无法插入这些记录?我应该以不同的方式循环吗?有没有更好的方法呢?
答案 0 :(得分:2)
您只需每1000行提交一次。你没有提交最后一批。在END LOOP之后添加提交;
BEGIN
c_count := 0; -- this variable is declared at the package level outside of this function
for rec in all_entities LOOP
BEGIN
insert into reporting (
select *
from table(get_report_data(rec.id_number))
);
c_count := c_count + 1;
if MOD(c_count, 1000) = 0 Then
-- record status to table
commit;
end if;
EXCEPTION
WHEN OTHERS THEN
-- record exception to table
END;
END LOOP;
COMMIT; -- <-- Add this commit to pick up last few records
return V_RESULT;
END;
答案 1 :(得分:1)
这可能是并发问题吗?如果在循环运行时在ENTITY表中提交了记录,则无法对其进行处理。
顺便说一下:以这种方式使用其他人就是在寻找麻烦。BTW2:为什么不简单地使用:
INSERT INTO reporting
SELECT rep.*
FROM entity e
CROSS JOIN table(get_report_data(e.id_number)) rep;