Как говорит Том Кайт (вице-президент Oracle Corp.):
Моя мантра, которой я буду придерживаться большое спасибо:
Вы должны сделать это в одном операторе SQL, если это вообще возможно.
Если вы не можете сделать это в одном операторе SQL, сделайте это в PL / SQL.
Если вы не можете сделать это в PL / SQL, попробуйте хранимую процедуру Java.
Если вы не можете сделать это в Java, сделайте это во внешней процедуре C.
Если вы не можете сделать это во внешней подпрограмме C, вы можете захотеть
всерьез задумайтесь о том, зачем вам это нужно…
мыслить в наборах ...
узнать все, что можно узнать о SQL ...
Вы должны выполнить свое обновление в SQL, если можете. Если вам нужно добавить индекс, чтобы сделать это, то это может быть предпочтительнее, чем цикл по коллекции, заполненной BULK COLLECT.
Если, однако, это какое-то задание ....
Вы должны указать это как таковое, но вот как вы это сделаете.
Я предположил, что у вашего сервера БД нет возможности хранить 10 миллионов записей в памяти, поэтому вместо ОБЪЕМНОГО СОБИРАТЬ все 10 миллионов записей за один раз я поместил ОБЪЕМНЫЙ СБОР в цикл, чтобы уменьшить нагрузку на память. Если это не так, то вы можете пропустить цикл массового сбора.
DECLARE
c_bulk_limit CONSTANT PLS_INTEGER := 500000;
--
CURSOR names_cur
IS
SELECT name
FROM table1;
--
TYPE namesValuesType IS TABLE OF table1.name%TYPE
INDEX BY PLS_INTEGER;
namesValues namesValuesType;
BEGIN
-- Populate the collection
OPEN name_cur;
LOOP
-- Fetch the records in a loop limiting them
-- to the c_bulk_limit amount at a time
FETCH name_cur BULK COLLECT INTO namesValues
LIMIT c_bulk_limit;
-- Process the records in your collection
FORALL x IN INDICES OF namesValues
UPDATE xyz
SET is_valid ='Y'
WHERE name = namesValue(x)
AND is_valid != 'Y';
-- Set up loop exit criteria
EXIT WHEN namesValues.COUNT < c_bulk_limit;
END LOOP;
CLOSE name_cur;
-- You want to update all remaining rows to 'N'
UPDATE xyz
SET is_valid ='N'
WHERE is_valid IS NULL;
EXCEPTION
WHEN others
THEN
IF name_cur%ISOPEN
THEN
CLOSE name_cur;
END IF;
-- Re-raise the exception;
RAISE;
END;
/
В зависимости от размеров сегментов отката и т. Д. Вы можете захотеть выполнить временные коммиты в цикле массового сбора, но имейте в виду, что вы не сможете откатить эти изменения. Я намеренно не добавил к нему никаких коммитов, чтобы вы могли выбрать, где их разместить в соответствии с вашей системой.
Вы также можете изменить размер константы c_bulk_limit в зависимости от доступных вам ресурсов.
Ваше обновление будет вызывать проблемы, если таблица xyz велика и в столбце имени нет индекса.
Надеюсь, это поможет ...