Ваш PL/SQL блок, используя предложение АРД, в должны быть завершены, как это (somce вы новичок в PL/SQL Я добавляю некоторые синтаксические предложения, которые вы могли бы быть заинтересованы в):
BEGIN
-- WHILE (TRUE) can be omitted: "loop ... end loop;"
-- already is an endless loop
LOOP
UPDATE CUSTOMERS
SET ACTIVE = 'N'
WHERE ACTIVE='Y'
AND rownum <= 1000;
exit when sql%notfound; -- notice that exit accepts "when condition"
--IF sql%notfound THEN -- you can avoid a if/endif by using "exit when"
-- EXIT;
-- END IF;
COMMIT;
END LOOP;
commit; -- you missed this commit for the last iteration
END;
Не соблазн поставить «commit» перед «exit when sql% notfound»: после «commit» sql% notfound всегда ложно, и ваш цикл будет действительно бесконечным.
Позвольте мне указать, что для обеспечения эффективности этот подход требует индексации столбца «ACTIVE»!
Если у вас нет индекса в столбце «active», каждое «обновление» будет принудительно перезапускать полное сканирование таблицы с самого начала, чтобы найти следующие 1000 записей, которые все еще необходимо обновить.
Этот другой подход, который я предлагаю, использует некоторые усовершенствованные функции PL/SQL, которые вы, как ученик, интересуетесь (rowid, «таблица», объемные выборки курсора и «forall»), и делает только одно сканирование таблицу, которая должна быть обновлена, поэтому (в случае отсутствия индексов) она работает лучше, чем предыдущий подход. Имейте в виду, что если у вас есть индексы, это медленнее (но использование фокусов, объемных сборок и доступа к рядам, это не так уж медленнее), но он может пригодиться в случаях, когда вещи сложнее (например: когда условие where должно получить доступ к данным из других таблиц, используя сложные объединения, которые не могут быть сделаны быстрее). Бывают случаи, когда «где» является настолько сложным и медленным, что вы действительно не хотите повторять его снова и снова, используя подход «where rownum < = 1000».
declare
type rowid_array is table of rowid;
ids rowid_array;
cursor cur is
select rowid as id
from CUSTOMERS
where ACTIVE='Y';
begin
open cur;
loop
fetch cur bulk collect into ids limit 1000;
exit when ids.count = 0;
forall c in ids.first .. ids.last
update CUSTOMERS set ACTIVE='N';
commit;
end loop;
end;
Зачем это делать партиями? (Oracle отлично способен обновлять записи 1M в одном заявлении) –