批量更新执行流程如何工作

Posted

技术标签:

【中文标题】批量更新执行流程如何工作【英文标题】:how dows bulk update flow of execution works 【发布时间】:2013-09-05 20:38:14 【问题描述】:

我正在编写一些代码,这些代码会将数十亿数据从一个表复制到另一个表,并且我们不希望该过程在出现异常时停止。所以我把脚本放在了(不是把 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;

现在基于这个伪代码我有 2 个问题

    我正在 forall 循环中删除我的收藏。如果出现异常并且我决定从 dml_errors 块中的集合中获取一些信息,我会在其中包含集合元素吗?如果是,那么在登录后删除它们是否安全? 由于我将 forall 保留在 begin-exception-end 块中,它会继续迭代吗?

【问题讨论】:

【参考方案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 收藏中删除。这似乎没有给你带来任何好处。这只是花费一些时间。如果您的缩进表示您预期的控制流,那么您认为deleteforall 循环的一部分——这是不正确的。只有insertforall 的一部分,delete 是一个单独的操作。

如果您的第二个问题是“如果在迭代 N 中引发异常,循环是否仍会执行第 N+1 次提取”,答案是肯定的。

有一点需要注意——因为error_count 没有被初始化,所以它总是为NULL。您需要将其初始化为 0 以记录错误总数。

【讨论】:

我在这里使用 pl/sql 有两个原因。 1,src 表在远程数据库中,所以我将使用 dblinks。 2, src 表有数十亿条记录,我必须与本地表进行比较,如果丢失,我必须将其插入单独的表中。所以我想在批处理中做到这一点。 关于error_log_table的问题。在阅读了几个教程后,我注意到我不能使用forall。我对吗 ?那我该如何使用批量插入器?其次,err_log 功能不记录唯一约束违规(在我的情况下这是最可能的) @Em Ae - 源表是远程的这一事实似乎无关紧要。您可以使用 SQL 插入目标表中不存在的所有行(或者,如果您确实想要更新本地表,如果源中有匹配的行,则更有可能执行 MERGE)。如果您使用 DML 错误日志记录,则不会使用 forall,因为您没有使用 PL/SQL 集合。并且 DML 错误日志记录肯定会记录唯一的约束违规。

以上是关于批量更新执行流程如何工作的主要内容,如果未能解决你的问题,请参考以下文章

Android逆向小技巧③:批量注入日志,打印目标程序执行流程

Android逆向小技巧③:批量注入日志,打印目标程序执行流程

代码审查后更新拉取请求的首选 Github 工作流程

基本的ado.net本地事务处理流程

如何在 EF Core 3.1 中使用脚手架流程更新我的实体 - 执行超时已过期

Java基础学习总结(194)—— Java 多线程 + List 分段完美解决导入等批量更新场景问题