Oracle: триггеры внутри транзакции (2 оператора) - PullRequest
2 голосов
/ 29 июня 2011

Я работаю над БД Oracle 10g, и у меня проблема с моими триггерами внутри транзакции. Table A имеет 3 триггера: один перед вставкой, один перед обновлением и последний перед удалением. Всякий раз, когда срабатывает триггер, он записывает строку в table B, что-то вроде журнала. Все триггеры настроены на "before xxx" и "on each row". Используя отдельные запросы, я вижу, что они работают.

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

Возможно, я что-то неправильно настроил. Это что-то происходит из конфигурации триггера?

Ответы [ 3 ]

6 голосов
/ 29 июня 2011

У второго триггера нет причин не срабатывать, происходит что-то еще.

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

SQL> CREATE TABLE a (ID NUMBER);

Table created

SQL> CREATE TABLE b (action VARCHAR2(3), id_old NUMBER, id_new NUMBER);

Table created

SQL> CREATE TRIGGER trg_a_ins BEFORE INSERT ON a FOR EACH ROW
  2  BEGIN
  3     INSERT INTO b VALUES ('ins', :old.id, :new.id);
  4  END;
  5  /

Trigger created

SQL> CREATE TRIGGER trg_a_upd BEFORE UPDATE ON a FOR EACH ROW
  2  BEGIN
  3     INSERT INTO b VALUES ('upd', :old.id, :new.id);
  4  END;
  5  /

Trigger created

SQL> CREATE TRIGGER trg_a_del BEFORE DELETE ON a FOR EACH ROW
  2  BEGIN
  3     INSERT INTO b VALUES ('del', :old.id, :new.id);
  4  END;
  5  /

Trigger created

SQL> INSERT INTO a VALUES (1);

1 row inserted

SQL> UPDATE a SET ID = 2 WHERE ID = 1;

1 row updated

SQL> DELETE FROM a WHERE ID = 2;

1 row deleted

SQL> select * from b;

ACTION     ID_OLD     ID_NEW
------ ---------- ----------
ins                        1
upd             1          2
del             2 
0 голосов
/ 30 июня 2011

Возможно (и желательно), чтобы ORM «сжал» несколько изменений в одной записи. Таким образом, код может обновлять три атрибута, и ORM может обновлять запись / экземпляр несколько раз в своем кэше, но отправлять только один оператор UPDATE в конце транзакции. Или, если запись в конечном итоге была удалена, она может пропустить любые обновления и просто удалить исходную запись.

Тем не менее, я не могу объяснить, почему запись может быть удалена без срабатывания триггера DELETE. Я предполагаю, что вы используете реальное удаление, а не «мягкое» удаление (оно помечает запись как удаленную и просто скрывает ее от просмотра).

0 голосов
/ 29 июня 2011

Как говорит @Vincent Malgrat, происходит что-то еще. Есть ли в таблице B столбец даты с уникальным индексом? Первая возможность, которая приходит на ум, состоит в том, что две записи вставляются с одинаковым значением даты (аудита) с точностью до секунды; столкновение индекса вызывает ошибку при второй вставке из удаления; но это раздавлено внутри триггера удаления. Я знаю, что это скорее спекуляция, и она будет менее вероятной с колонкой меток времени, и иногда будет работать так, как ожидалось, если бы время было правильным.

...