Ошибка мутации после триггера вставки - PullRequest
2 голосов
/ 12 декабря 2011

Приведенный ниже код дает мутантную ошибку. Может ли any1 PLS помочь в решении этой проблемы.

    CREATE OR REPLACE TRIGGER aso_quote_cuhk_trigger
    BEFORE INSERT
    ON aso.aso_quote_headers_all
    FOR EACH ROW
    BEGIN
     UPDATE aso.aso_quote_headers_all
     SET quote_expiration_date=sysdate+90
     where quote_header_id=:new.quote_header_id;
    END;
    /

Ответы [ 2 ]

8 голосов
/ 12 декабря 2011

В oracle есть два уровня триггеров: уровень строки и уровень таблицы.

Триггеры уровня строки выполняются for each row. Триггеры уровня таблицы выполняются для каждого оператора, даже если оператор изменил более одной строки.
В триггере уровня строки вы не можете выбрать / обновить саму таблицу, в которой есть триггер: вы получите ошибку с мутацией.

В этом случае нет необходимости в выражении UPDATE. Просто попробуйте это:

CREATE OR REPLACE TRIGGER aso_quote_cuhk_trigger
BEFORE INSERT
ON aso.aso_quote_headers_all
FOR EACH ROW
BEGIN
 :new.quote_expiration_date=sysdate+90;     
END;
/

EDIT Раджеш упомянул, что, возможно, перед вставкой новой строки OP хочет обновить все остальные записи в таблице aso_quote_headers_all.

Ну, это выполнимо, но это немного сложно. Чтобы сделать это правильно, вам понадобится

  1. Пакет pl / sql и переменная в заголовке пакета, которая изменяется триггерами. Эта переменная может быть списком, содержащим идентификаторы вновь вставленных записей. Уровень строки после триггера вставки добавит новый идентификатор в список. Содержимое этой переменной пакета будет различным для каждого отдельного сеанса, поэтому давайте назовем эту переменную session_variable.
  2. Уровень строки после триггера вставки, который добавит новый идентификатор к session_variable.
  3. Уровень таблицы после триггера вставки, который будет получать идентификаторы из session_variable, обработать идентификатор и затем удалить его из session_variable. Этот триггер может выполнить необходимые выборки / обновления для aso_quote_headers_all. После обработки вновь вставленного идентификатора этот триггер должен убедиться, что он удален из session_variable.
3 голосов
/ 22 апреля 2013

Я понимаю, что вы уже решили свою проблему. Однако я добавляю этот ответ ниже, чтобы помочь кому-либо еще сталкивающемуся с подобной проблемой, с которой мы столкнулись.

Недавно я столкнулся с проблемой изменяющейся таблицы (ORA-04091: таблица XXXX изменялась, триггер / функция может ее не видеть), и после поиска в ней реализована функция Составные триггеры , доступная в 11g. Если вы используете 11g, следующий составной триггер решил бы вашу проблему.

CREATE OR REPLACE TRIGGER aso_quote_cuhk_trigger
FOR INSERT ON aso.aso_quote_headers_all
COMPOUND TRIGGER

    row_id    rowid;

    AFTER EACH ROW IS
    BEGIN
      row_id := :new.rowid;
    END AFTER EACH ROW;

    AFTER STATEMENT IS
    BEGIN
      UPDATE aso.aso_quote_headers_all 
      SET quote_expiration_date = sysdate+90 
      WHERE rowid = row_id;
    END AFTER STATEMENT;
END aso_quote_cuhk_trigger;
/

Несколько слов о том, как это работает. Этот составной триггер запускает 2 события:

  1. Сначала ПОСЛЕ КАЖДОЙ СТРОКИ, где мы записываем rowid вновь вставленной строки
  2. Далее следует ПОСЛЕ ЗАЯВЛЕНИЯ, где мы обновляем таблицу с использованием rowid (захваченного во время первого события) в предложении WHERE.

Полезная ссылка , если вы хотите узнать больше о сложных триггерах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...