我正在编写一些代码,这些代码将数十亿的数据从一个表复制到另一个表,我们不希望在异常的情况下停止该过程。所以我正在编写脚本(不是100%可编译的语法)
dml_errors exception;
errors number;
error_count number;
pragma exception_init (dml_errors, -24381);
---------
open cursor;
begin loop;
fetch cursor bulk collect into tbl_object limit batch_size;
exit when tbl_object.count = 0;
-- perform business logic
begin
forall in tbl_object save exceptions;
insert into table;
tbl_object.delete;
exception
when dml_errors then
errors := sql%bulk_exceptions.count;
error_count := error_count + errors;
insert into log_table (tstamp, line) values (sysdate, SUBSTR('[pr_procedure_name:'||r_guid||'] Batch # '||batch_number - 1||' had '||errors||' errors',1,300));
end;
end loop;
close cursor;
end procedure;
现在根据这个pseduo代码我有两个问题
答案 0 :(得分:1)
您确定需要在这里使用PL / SQL吗?除非您在业务逻辑中进行了大量处理,而您没有向我们展示无法在SQL中完成的处理,否则我倾向于使用DML error logging。这将更有效,更少的代码,并为您提供更好的日志记录。
DBMS_ERRLOG.CREATE_ERROR_LOG( 'DESTINATION_TABLE' );
INSERT INTO destingation_table( <<columns>> )
SELECT <<columns>>
FROM source_table
LOG ERRORS
REJECT LIMIT UNLIMITED;
我认为没有理由从您的tbl_object
集合中删除。这似乎并没有让你获得任何好处。这只是花费一些时间。如果您的缩进表示您预期的控制流程,那么您认为delete
是forall
循环的一部分 - 这是不正确的。只有insert
是forall
的一部分,delete
是一个单独的操作。
如果你的第二个问题是“如果在迭代N中引发异常,那么循环是否仍会进行第N + 1次获取”,答案是肯定的,它会。
有一点需要注意 - 由于error_count
未初始化,因此它始终为NULL。您需要将其初始化为0,以便记录错误总数。