我希望每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太小。
答案 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交谈后,我们决定放弃这种方法。