FORALL не является циклической конструкцией: его нельзя отделить от его оператора DML.
когда я пытался оценить, является ли одно поле из источника пустым
Необходимо выполнить цикл по заполненной коллекции и исправить это перед выполнением FORALL ... INSERT.
CREATE OR REPLACE PACKAGE BODY MYSCHEMA.MYPKG AS
PROCEDURE MYPROCEDURE IS
BEGIN
OPEN CUR_MYDATA;
LOOP
FETCH CUR_MYDATA BULK COLLECT INTO l_name,l_lastname,l_id,l_socnum;
EXIT WHEN l_name.count = 0;
for idx in 1 .. l_socnum.count() loop
IF l_socnum(idx) IS NULL THEN
select oo.socnum
into l_socnum(idx)
from other_origin
where oo.id = l_id(idx);
END IF;
end loop;
forall i IN 1 .. l_name.COUNT
INSERT INTO destiny (
d_name,
d_lastname,
d_id,
d_socnum)
VALUES (
l_name(i),
l_lastname(i),
l_id(i),
l_socnum(i));
END LOOP;
END MYPROCEDURE;
END MYPKG;
Другие заметки.
- Проверьте, возвращает ли выборка какие-либо записи сразу после выполнения выборки. В противном случае ваш код будет пытаться выполнить код над пустой коллекцией, что приведет к сбою.
- Вы должны определить коллекцию на основе целевой таблицы
%rowtype
: это проще, чем определять и обрабатывать несколько коллекций на основе столбцов.
Кроме того, ваш реальный код может быть намного сложнее, чем то, что вы разместили здесь, но если у вас большой объем данных для переноса, то при использовании чистого SQL будет гораздо больше выигрыша в производительности, чем в процедуре:
INSERT INTO DESTINY (
D_NAME,
D_LASTNAME,
D_ID,
D_SOCNUM
)
SELECT
o.name,
o.last_name,
o.id,
coalesce(o.socnum, oo.socnum)
FROM
origin o
left outer join other_origin oo
on oo.id = o.id
WHERE
1=1
AND o.name like upper ('a%');