每1000行提交一次

时间:2018-07-03 10:29:25

标签: sql oracle sql-delete ora-01555

我希望每1000行执行一次提交,直到删除所有记录为止,我们有超过一百万条记录要删除。

最初:

private static final String DELETE_OLD_REPORTS_FROM_REPORTING =
-            "DELETE FROM A_REPORTING\n" +
-            "WHERE ID IN(" +
-            "SELECT ID FROM A_REPORTING\n" +
-            "WHERE STATUS = 'LOADED'\n" +
-            "AND CREATE_DT < TO_DATE(:createdDate, 'dd-mon-yyyy'))";

我正在考虑做这样的事情:

"BEGIN\n" +
                "LOOP\n" +
                    "DELETE FROM A_REPORTING\n" +
                    "WHERE ID IN(" +
                    "SELECT ID FROM A_REPORTING\n" +
                    "WHERE STATUS = 'LOADED'\n" +
                    "AND CREATE_DT < TO_DATE(:createdDate, 'dd-mon-yyyy')\n+" +
                    "AND ROWNUM <= 10000);\n" +
                    "EXIT WHEN SQL%rowcount < 9999;\n" +
                    "COMMIT;\n" +
                "END LOOP;\n"+
            "COMMIT;\n" +
            "END";

但是,有更好的方法吗?这样做的原因是因为我们收到了ORA-01555错误:

  

ORA-01555:快照太旧:名称为“%segname”的回退段号%n太小。

3 个答案:

答案 0 :(得分:1)

这听起来很适合批量收集!

declare

  d_created_date   date   := to_date(:createddate, 'dd-mon-yyyy'); -- define :createddate here

  -- get all rows you want to delete
  cursor cur_delete_records is
  select r.rowid 
    from a_reporting r
   where r.status = 'LOADED'
     and r.create_dt < to_date(d_created_date, 'dd-mon-yyyy');

  -- collection to store rows
  type t_delete_records   is table of cur_delete_records%rowtype;
  rec_delete_records      t_delete_records;

begin

  open cur_delete_records;
    loop
      fetch cur_delete_records
      bulk collect into rec_delete_records
      limit 1000; -- here's the 1,000 record max per loop
      exit when nvl(rec_delete_records.count, 0) = 0;

      forall x in rec_delete_records.first .. rec_delete_records.last

        delete from a_reporting r
         where r.rowid = rec_delete_records(x).rowid;

        commit;

    end loop;
  close cur_delete_records;

end;
/

答案 1 :(得分:0)

您可以使撤消表空间足够大,以便可以将原始删除语句的所有数据更改都保留在撤消中。然后,您可以增加undo_retention参数,使其比原始delete语句运行所需的时间更长。因此,如果运行删除操作需要1个小时,请将撤消保留时间设置为4个小时,并继续增加撤消表空间的大小,直到在运行删除操作时您未收到ORA-01555为止。除非行非常大,否则要删除的行数不是一百万。您应该可以通过撤消来阻止ORA-01555。

鲍比

答案 2 :(得分:0)

谢谢大家。在与DBA交谈后,我们决定放弃这种方法。