Лишенный всех несоответствий, я думаю, ваш вопрос прост.
Этот оператор обновления выполняется в SQL:
update xy set id = id + (SELECT min(id) FROM xy);
И этот анонимный блок также запускается:
begin
update xy set id = id + 100;
end;
Но объединение двух не работает:
begin
update xy set id = id + (SELECT min(id) FROM xy);
end;
Возможно, вы столкнулись с ограничением более старого Oracle. До 9i механизм SQL и механизм PL / SQL SQL всегда были не синхронизированы. Поэтому последние функции, поддерживаемые в SQL, часто не поддерживаются в PL / SQL. Кажется, у вас есть один из них.
Поскольку 9i Oracle стремилась поддерживать синхронизацию двух механизмов, поэтому гораздо реже находить вещи, которые работают в SQL, но не в PL / SQL.
Учитывая характер вашей задачи, обновление вашей версии Oracle вышло. Итак, все, что я могу предложить, это то, что у вас есть две процедуры, одна из которых поддерживает синтаксис подзапроса (избегая необходимости в таких подзапросах. Примерно так:
CREATE OR REPLACE FUNCTION xy_sqfn
(main_query VARCHAR2
, sub_query VARCHAR2 )
RETURN NUMBER
IS
n pls_integer;
BEGIN
execute immediate sub_query into n;
EXECUTE IMMEDIATE 'BEGIN '||main_query||'; END;'
using n;
RETURN 5;
END;
Назовите это так
result := xy_sqfn ('update xy set id = id + :1'
, 'SELECT min(id) FROM xy');
Теперь этот подход не будет работать для коррелированных подзапросов. Так что, если у вас есть какой-либо из них, вам нужно будет снова сделать что-то другое.
Кстати, использование прагмы AUTONOMOUS TRANSACTION для того, чтобы помешать выполнению DML в операторе SELECT, довольно ужасно. Почему бы просто не запустить функции в PL / SQL? Или использовать процедуры? Полагаю, вы скажете, что это не имеет значения, потому что вы просто пишете какой-то неуклюжий код для поддержки миграции данных. Это достаточно справедливо, но для будущих искателей: не делайте этого! Это очень плохая практика!