Мы недавно обновили Oracle 10 до Oracle 11.2.После обновления я начал видеть ошибку изменяющейся таблицы, вызванную функцией, а не триггером (с которым я никогда раньше не сталкивался).Это старый код, который работал в предыдущих версиях Oracle.
Вот сценарий, который вызовет ошибку:
create table mutate (
x NUMBER,
y NUMBER
);
insert into mutate (x, y)
values (1,2);
insert into mutate (x, y)
values (3,4);
Я создал две строки.Теперь я удвою свои строки, вызвав этот оператор:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;
Это не обязательно, чтобы дублировать ошибку, но это поможет с моей демонстрацией позже.Таким образом, содержимое таблицы теперь выглядит так:
X,Y
1,2
3,4
2,3
4,5
Все хорошо.Теперь для забавной части:
create or replace function mutate_count
return PLS_INTEGER
is
v_dummy PLS_INTEGER;
begin
select count(*)
into v_dummy
from mutate;
return v_dummy;
end mutate_count;
/
Я создал функцию для запроса моей таблицы и возврата счетчика.Теперь я объединю это с оператором INSERT:
insert into mutate (x, y)
select x + 2, y + 2
from mutate
where mutate_count() = 4;
Результат?Эта ошибка:
ORA-04091: table MUTATE is mutating, trigger/function may not see it
ORA-06512: at "MUTATE_COUNT", line 6
Итак, я знаю, что вызывает ошибку, но мне любопытно, почему почему .Разве Oracle не выполняет SELECT, получает набор результатов и , а затем выполняет массовую вставку этих результатов?Я ожидал бы только ошибку изменяющейся таблицы, если записи уже были вставлены до завершения запроса.Но если бы Oracle это сделал, разве более раннее утверждение:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;
не запустило бы бесконечный цикл?
ОБНОВЛЕНИЕ:
По ссылке Джеффри я нашел это в Oracle docs :
По умолчанию Oracle гарантирует согласованность чтения на уровне инструкций.Набор данных, возвращаемых одним запросом, согласуется с одним моментом времени.
Есть также комментарий автора в его посте :
Можно спорить, почему Oracle не обеспечивает эту «согласованность чтения на уровне инструкций» для повторных вызовов функций, которые появляются внутри инструкций SQL.Насколько я могу судить, это можно считать ошибкой.Но в настоящее время это так.
Правильно ли я считаю, что это поведение изменилось между версиями Oracle 10 и 11?