INSERT триггер для вставки записи в ту же таблицу - PullRequest
2 голосов
/ 17 ноября 2011

У меня есть триггер, который срабатывает при вставке новой записи в таблицу, в которую я хочу вставить новую запись в той же таблице.
Мой триггер:

create or replace trigger inst_table
after insert on test_table referencing new as new old as old  
for each row
declare 
      df_name varchar2(500);
      df_desc varchar2(2000);

begin
      df_name := :new.name;
      df_desc := :new.description;

     if inserting then
          FOR item IN (SELECT pid FROM tbl2 where pid not in(1))
             LOOP
                 insert into test_table (name,description,pid) values(df_name,df_desc,item.pid); 
             END LOOP;    
     end if; 
end;

, он выдает ошибкукак

ORA-04091: table TEST_TABLE is mutating, trigger/function may not see it

Я думаю, что это мешает мне вставить в ту же таблицу.
так, как я могу вставить эту новую запись в ту же таблицу.

Примечание: - Я использую Oracle в качестве базы данных

Ответы [ 3 ]

10 голосов
/ 17 ноября 2011

Мутация происходит каждый раз, когда у вас есть триггер уровня строки, который модифицирует таблицу, по которой вы запускаете. Проблема в том, что Oracle не может знать, как себя вести. Вы вставляете строку, сам триггер вставляет строку в ту же самую таблицу , и Oracle запутывается, потому что эти вставки в таблицу из-за триггера тоже подвергаются действию триггера? *

Решение состоит из трех этапов.

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

2.) Уровень строки до или после триггера, который сохраняет информацию о строке в переменных пакета, которые были созданы на предыдущем шаге.

3.) Уровень оператора после триггера, который вставляет в таблицу все строки, которые сохраняются в переменной пакета.

Пример этого можно найти здесь:

http://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936

Надеюсь, это поможет.

1 голос
/ 17 ноября 2011

Хотя после жалоб на плохие триггеры, есть другое решение.

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

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

1 голос
/ 17 ноября 2011

Я бы сказал, что вы должны смотреть на ДРУГОЙ, чем триггеры, чтобы достичь этого. Как упоминалось в ответе Марка Бобака, триггер вставляет строку, а затем для каждой строки, вставленной триггером, который затем должен вызвать триггер, чтобы вставить больше строк.

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

Триггеры могут использоваться для решения простых задач, но при решении более сложных проблем они будут просто вызывать головные боли.

Стоит прочитать ответы на этот дублирующий вопрос , опубликованный APC, а также эти эту статью от Тома Кайта. Кстати, статья также упоминается в дубликате вопроса, но ссылка сейчас устарела.

...