使用我的 ORACLE 数据库请求提交每 200 个客户端的最佳方法是什么

What is the best way to commit every 200 clients with my ORACLE database request

我的数据库中有一个每天启动的请求。它用于最多删除大约 750 个客户端的行。现在我们想保留该请求,但我们需要每 200 个客户端提交一次。

这是原始请求:

delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR);
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR);

如您所见,要删除的客户端 ID 列表在另一个 table 中。我们通过 select 请求获得它。

select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR

该列表最多可以包含 750 个客户端 ID。 因此,为了承诺每 200 个客户,我已经这样做了:

declare i number := 0;
begin
  for r in (select ID_CLI from MKTMLF.TMP_ID_CLI_SUPPR)
  loop
    delete from MYSCHEMA.TABLE1 where id_cli = r.id_cli;
    delete from MYSCHEMA.TABLE2 where id_cli = r.id_cli;
    i := i+1;
    if mod(i, 200) = 0 THEN   
          COMMIT;
    end if;
   end loop;
 commit;
end;

但我的同事告诉我这是个坏主意,因为如果我们要删除 750 个 ID,这两个请求将是 750 次,所以 750*2 = 1500 个请求!他告诉我使用 ROWNUM 来获取前 200 个 ID,然后提交其他 200 个等等......所以我尝试了一下,它看起来像这样:

declare listTotal number := 0;
begin
    select count(1) into listTotal from MKTMLF.TMP_ID_CLI_SUPPR;
    delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR where ROWNUM < 201);
    delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR where ROWNUM < 201);
commit;
if listTotal > 200 THEN
    delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 200 and r < 401);
    delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 200 and r < 401);
end if;
commit;
if listTotal > 400 THEN
    delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 400 and r < 601);
    delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 400 and r < 601);
end if;
commit;
if listTotal > 600 THEN
    delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 600 and r < 751);
    delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 600 and r < 751);
end if;
commit;
end;

所以我问自己实现这一目标的最佳方法是什么?我发现第二种方式有点太复杂但也许更快?也许您有其他更好的方法?

你说你想每 200 次提交一次..."Because sometimes it fails before the end"

根据该信息,我建议使用 ERROR_LOGGING 子句并将其保存在单个语句中。 我不认为将其分解为每 200 次提交是处理这种情况的最佳方法。

以下是我的推荐:

1) 为您的两个 table 创建错误 table:

  EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('TABLE1', 'TABLE1_ERRLOG');
  EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('TABLE2', 'TABLE2_ERRLOG');

(或您正在处理的每个 table 1 个)

这是一次性设置..不必每天重做。

2) 让你的 "daily job" 运行 以下删除语句..包括 LOG ERRORS 子句:

  delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR) 
     LOG ERRORS INTO TABLE1_ERRLOG ('Daily Delete1') REJECT LIMIT 750 ;  

您可以为 REJECT LIMIT 输入任何您想要的数字..我现在输入 750..因为您提到您每天最多处理 750 个?这将允许脚本尝试删除所有内容......并报告所有失败的内容。如果您选择一个较低的数字,它会在达到那么多失败的删除后停止。调整以满足您的要求。 ;)

  delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
     LOG ERRORS INTO TABLE2_ERRLOG ('Daily Delete2') REJECT LIMIT 750 ;  

3) 让作业在 运行ning 之后查看那 2 个错误日志 tables 并在记录存在时做出相应响应 ...

您可以查看它们并随意处理它们...然后 re-run 随时删除 re-try。

(注意:删除 non-existent 记录就可以了,在这种情况下它不会记录任何错误...)

请注意,此 ERROR_LOGGING 子句适用于 INSERT、UPDATE 和 DELETE 语句。而且你只需要 1 ERROR table 每个基地 table ...不管 INS/UPD/DEL 你 运行 ..

换句话说...在创建 TABLE1_ERRLOG 之后...然后您可以 运行:

     delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR) 
     LOG ERRORS INTO TABLE1_ERRLOG ('Daily Delete1') REJECT LIMIT 750 ;  

     INSERT into MYSCHEMA.TABLE1 ( select * from ... whatever ..)
        LOG ERRORS INTO TABLE1_ERRLOG ('Daily Insert1') REJECT LIMIT 750 ;  

还有:

     UPDATE MYSCHEMA.TABLE1 set some_col = some_value
        where <some condition>
        LOG ERRORS INTO TABLE1_ERRLOG ('Daily Update1') REJECT LIMIT 750 ;  

而且他们会将所有错误转储到同一个错误日志中 table:TABLE1_ERRLOG 您可以查看列:ORA_ERR_TAG$ 以查看它是 Del、Ins 还是 Upd .. (即您发送的 "comment" .. 我在上面的示例中使用了 "Daily Delete1"、"Daily Insert1" 和 "Daily Update1")

甲骨文 10: https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_8005.htm

LOG ERRORs 子句示例:

https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_9014.htm#BCEGDJDJ

甲骨文 11: https://docs.oracle.com/cloud/latest/db112/SQLRF/statements_8005.htm#SQLRF01505

LOG ERRORs 子句示例:

https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9014.htm#i2121671