Использование BULK COLLECT с rownum
Внизу запроса Bulk выбирает, а затем обновляет записи в цикле. Я хочу использовать конструкции BULK COLLECT INTO и FORALL для повышения производительности. Но запрос использует rownum для обновления столбца в цикле. Можно ли в любом случае использовать BULK COLLECT INTO при получении rownum?
FOR rec IN
(SELECT rownum rn,
b.*
FROM
(SELECT *
FROM temp_final a
WHERE reid = 1
AND retype = 9
AND sid = 'r123'
AND pid = 2191
ORDER BY a.horder DESC nulls last,
sname ,
rowgroup ,
dpct DESC nulls last ,
name
) b
)
LOOP
UPDATE temp_final
SET horder=rec.rn
WHERE reid = 1
AND retype = 9
AND sid = 'r123'
AND pid = 2191
AND mid =rec.mid;
END LOOP;
Спасибо
2 ответа
Решение
Вам не нужен массовый сбор, то, что пытается сделать ваше обновление pl/sql, может быть переписано как единое целое MERGE INTO
заявление, которое было бы гораздо эффективнее, чем использование FORALL
, Если вы все еще настаиваете на использовании forall, вы можете преобразовать этот MERGE в блок forall.
MERGE INTO temp_final tgt USING (
SELECT rowid,
ROW_NUMBER() OVER(
ORDER BY
horder DESC NULLS LAST,sname,rowgroup,dpct DESC NULLS LAST,name
) rn
FROM
temp_final
WHERE
reid = 1
AND retype = 9
AND sid = 'r123'
AND pid = 2191
)
src ON ( tgt.rowid = src.rowid )
WHEN MATCHED THEN UPDATE SET tgt.horder = src.rn;
Вы можете получить rowid вместе с начальным выбором, сбросить лот в массивы, а затем использовать его в своем FORALL, например,
declare
l_num_list sys.odcinumberlist := sys.odcinumberlist();
l_char_list sys.odcivarchar2list := sys.odcivarchar2list();
begin
SELECT rownum rn,rowidtochar(rid)
bulk collect into l_num_list, l_char_list
FROM
(SELECT a.*, rowid rid
FROM temp_final a
WHERE reid = 1
AND retype = 9
AND sid = 'r123'
AND pid = 2191
ORDER BY a.horder DESC nulls last,
sname ,
rowgroup ,
dpct DESC nulls last ,
name
) b;
forall i in 1 .. l_num_list.count
UPDATE temp_final
SET horder=l_num_list(i)
WHERE rowid = chartorowid(l_char_list(i));
end;
/