Это пакетная операция, верно? В этом случае вам следует избегать Row By Row и использовать обработку множеств. SQL это все о радости множеств.
Oracle обладает фантастическими возможностями массовой обработки SQL. Псевдокод, который вы вставили, выглядел бы примерно так:
declare
cursor c_oldrecs is
select * from your_table
where criterion between some_date and some_other_date;
type rec_nt is table of your_table%rowtype;
oldrecs_coll rec_nt;
begin
open c_oldrecs;
loop
fetch c_oldrecs into oldrecs_coll limit 1000;
exit when oldrecs_coll.count() = 0;
forall i in oldrecs_coll.first() oldrecs_coll.last()
insert into your_table_hist
values oldrecs_coll(i);
forall i in oldrecs_coll.first() oldrecs_coll.last()
delete from your_table
where pk_col = oldrecs_coll(i).pk_col;
end loop;
end;
/
Эта массовая обработка выполняется быстрее, поскольку она отправляет в базу данных тысячу операторов за раз вместо того, чтобы переключаться между PL / SQL и SQL тысячу раз. Предложение LIMIT 1000 предназначено для того, чтобы предотвратить огромный выбор PGA. Эта гарантия может не понадобиться в вашем случае, или вы можете работать с более высокой ценностью.
Я думаю, что ваша текущая реализация неверна. Лучше хранить только текущую версию в оперативной таблице и хранить все исторические версии в отдельной таблице. Используйте триггеры для ведения истории как части каждой транзакции.