ORACLE После триггера обновления: решение ошибки изменяющейся таблицы ORA-04091

Я пытаюсь создать триггер:

  create or replace trigger NAME_OF_TRIGGER
  after insert or update on table1
  REFERENCING OLD AS OLD NEW AS NEW
  for each row

автоматически заполнять пару необязательных полей при обновлении/вставке в таблицу.

Это требует от меня использования курсора, который выбирает из таблицы2, а также из таблицы1 (предмет триггера).

Есть ли способ избежать ошибки изменяющейся таблицы без использования временной таблицы для значений или автономной транзакции?


person JoséNunoFerreira    schedule 02.08.2011    source источник


Ответы (1)


«Есть ли способ избежать ошибки изменяющейся таблицы без использования временной таблицы для значений или автономной транзакции?»

tl;dr нет.


Ошибка изменяющейся таблицы вызвана запросом таблицы, которой принадлежит триггер, или таблиц, которые участвуют в отношениях внешнего ключа с таблицей-владельцем (по крайней мере, в более старых версиях базы данных, не уверен, что он все еще получает).

В правильно спроектированном приложении в этом нет необходимости. Вот почему многие люди рассматривают изменяющиеся таблицы как показатель плохого моделирования данных. Например, мутация часто связана с недостаточной нормализацией.


Перефразируя Джейми Завински: некоторые люди, сталкиваясь с исключением изменяющейся таблицы, думают: «Я знаю, я буду использовать автономные транзакции». Теперь у них две проблемы.


Иногда ошибки можно избежать, просто изменив значения :NEW в триггере BEFORE INSERT OR UPDATE или используя виртуальные столбцы. Но вам нужно опубликовать более подробную информацию, чтобы увидеть, применимы ли они.

Но лучший обходной путь - не нуждаться в каком-либо другом виде.

person APC    schedule 02.08.2011
comment
Спасибо! Это подтверждает все, что я читал об экспериментах. Теперь я меняю значения :new для триггера before; кажется работает! - person JoséNunoFerreira; 03.08.2011
comment
Что ж, в теории это хорошо, но что делать, если вы хотите использовать эту мутирующую таблицу в сложном объединении? У вас есть вторая временная таблица, в которую вы помещаете данные триггера, а затем используете эту временную таблицу в объединении? Что вы делаете, когда у вас есть сотни таких таблиц? Удвойте свою схему и создайте несколько версий каждого запроса, чтобы справиться со всеми возможностями любой присоединяемой таблицы, которая в настоящее время мутирует... или использовать динамический SQL? - person Dexter; 02.10.2013
comment
Таким образом, либо триггеры Oracle несколько бесполезны... либо я - предполагаю, что последний, вероятно, действителен, но ошибка мутирующего триггера - королевская лаваш. - person Rich Bianco; 11.04.2017
comment
@RichBianco - Вероятно, триггеры бесполезны или, по крайней мере, обычно полезны только в нескольких случаях использования. В основном изменяющиеся таблицы предупреждают нас о проблеме в модели данных или бизнес-процессе. - person APC; 11.04.2017