Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
Всем привет!
Был у меня один триггер BEFORE UPDATE OR INSERT
В нем в конце вызывалась функция для апдейта некоторого значения, но апдейт не происходил, потому что еще не было new-значения
Поэтому я перенес вызов этой функции в триггер AFTER UPDATE OR INSERT
И получил такую ошибку как в сабже.
Тексты триггеров любезно предоставляю на рассмотрение многоуважаемой публики:
CREATE OR REPLACE TRIGGER tr_pre_bre_instalments_bef
   BEFORE INSERT OR UPDATE
   ON premature_breach_instalments
   FOR EACH ROW

BEGIN
   IF INSERTING THEN
      :new.date_created := db_pink_common.fu_sysdate;

      :new.ins_pgm      := TRIM ( :new.ins_pgm);
   END IF;

   IF :new.due_date < pa_constants.c_null_date THEN
      :new.due_date := NULL;
   END IF;

   :new.user_id                      := db_pink_common.fu_getuser;
   :new.date_changed                 := db_pink_common.fu_sysdate;

   :new.total_instalment_amount      := NVL (:new.instalment_amount, 0) + NVL (:new.interests, 0) + NVL (:new.penalty_interests, 0)
                                        + NVL (:new.expenses, 0) + NVL (:new.unspecified_amount, 0);
END;

CREATE OR REPLACE TRIGGER tr_premature_breach_instal_aft
   AFTER INSERT OR UPDATE
   ON premature_breach_instalments
   FOR EACH ROW

DECLARE
   out_status_code          NUMBER (4) := 0;
   out_status_description   VARCHAR2 (255) := NULL;
BEGIN
   pa_premature_breach.pr_upd_amount_next_inst (  <--------------эта процедура переехала сюда
      in_case_no        => :new.case_no
     ,out_status        => out_status_code
     ,out_status_desc   => out_status_description);

   IF out_status_code < 0 THEN
      raise_application_error (
         -20000
        ,'Error during call to PA_PREMATURE_BREACH.PR_UPD_AMOUNT_NEXT_INST: ' || out_status_description);
   END IF;
END;


Как можно решить данную проблему?
Заранее благодарен за любую помощь
16 окт 14, 17:02    [16715521]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
-2-
Member

Откуда:
Сообщений: 15330
joe_satirus
Как можно решить данную проблему?
вбить в поиск ключевые слова.
16 окт 14, 17:06    [16715561]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
tru55
Member

Откуда: СПб
Сообщений: 19790
Что-то я не понял. Каких таких NEW-значений нет в BEFORE-триггере, но есть в AFTER-триггере?
16 окт 14, 17:08    [16715594]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
Это само собой разумеется
16 окт 14, 17:13    [16715647]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
tru55,

я наверное неправильно выразился. Но суть в том, что апдейт с помощью указанной ф-ции не происходил
16 окт 14, 17:14    [16715657]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
По поводу поиска по ключевым словам, вот направили сюда http://www.oracle-base.com/articles/11g/trigger-enhancements-11gr1.php , рекомендуют использовать COMPOUND TRIGGER

Кто об этом что-то слышал? Сможет ли это решить мою проблему?
16 окт 14, 17:16    [16715679]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
уувуукукуку
Guest
joe_satirus,

Ты бы разобрался с обычными триггерами.
Скорее всего решил бы свою проблемы с их помощью.
16 окт 14, 17:22    [16715745]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
уувуукукуку,
да, я тоже больше склоняюсь к этому варианту
вот у Тома разбирается похожая ситуация https://asktom.oracle.com/pls/asktom/ASKTOM.download_file?p_file=6551198119097816936
но пока не совсем понятно, как я смогу ее применить у себя...
16 окт 14, 17:33    [16715872]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
переделал как compound trigger. Сейчас проверю, как оно работает
16 окт 14, 18:20    [16716197]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
compound trigger не помог:
CREATE OR REPLACE TRIGGER tr_pre_bre_instal_compound
  FOR INSERT OR UPDATE OR DELETE ON premature_breach_instalments
    COMPOUND TRIGGER

  -- Global declaration.
  
   out_status_code          NUMBER (4) := 0;
   out_status_description   VARCHAR2 (255) := NULL;


  BEFORE EACH ROW IS
  BEGIN
    
   IF INSERTING THEN
      :new.date_created := db_pink_common.fu_sysdate;

      :new.ins_pgm      := TRIM ( :new.ins_pgm);
   END IF;

   IF :new.due_date < pa_constants.c_null_date THEN
      :new.due_date := NULL;
   END IF;

   :new.user_id                      := db_pink_common.fu_getuser;
   :new.date_changed                 := db_pink_common.fu_sysdate;

   :new.total_instalment_amount      := NVL (:new.instalment_amount, 0) + NVL (:new.interests, 0) + NVL (:new.penalty_interests, 0)
                                        + NVL (:new.expenses, 0) + NVL (:new.unspecified_amount, 0);
    
  END BEFORE EACH ROW;

  AFTER EACH ROW IS
  BEGIN
    pa_premature_breach.pr_upd_amount_next_inst (
      in_case_no        => :new.case_no
     ,out_status        => out_status_code
     ,out_status_desc   => out_status_description);

   IF out_status_code < 0 THEN
      raise_application_error (
         -20000
        ,'Error during call to PA_PREMATURE_BREACH.PR_UPD_AMOUNT_NEXT_INST: ' || out_status_description);
   END IF;
  END AFTER EACH ROW;

  

END tr_pre_bre_instal_compound;


Подскажите, что я делаю не так.
Заранее благодарен.
16 окт 14, 18:47    [16716318]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
ORA-20000: Error during call to PA_PREMATURE_BREACH.PR_UPD_AMOUNT_NEXT_INST: Unknown error.
ORA-06512: at "PINK.TR_PRE_BRE_INSTAL_COMPOUND", line 38
ORA-04088: error during execution of trigger 'PINK.TR_PRE_BRE_INSTAL_COMPOUND'
16 окт 14, 19:01    [16716388]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
Triggerr
Guest
что pa_premature_breach.pr_upd_amount_next_inst делает?
16 окт 14, 19:32    [16716511]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 242
joe_satirus,

FAQ N 7

Compound триггер всего лишь позволяет не создавать отдельный пакет, а собрать всю эту логику в одном месте.
16 окт 14, 21:34    [16716926]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
Да ну,

Спасибо за тынц, он реально прояснил ситуацию.
Что я из него понял:
нужно создать отдельный пакет, в котором мы будем аккумулировать массив значений для апдейта.
И собирать мы их будем в триггере after insert or update for each row.
А уже само обновление проведем в новом триггере after insert, в котором пройдемся по всему массиву накопленных значений в предыдущем триггере и для каждого значения вызовем нашу процедуру обновления.

Я правильно понял?
16 окт 14, 22:52    [16717285]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
вдогонку последней мысли - и вот всю эту логику с тремя триггерами удобно будет описать с помощью одного compound trigger'а
16 окт 14, 22:55    [16717299]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
-2-
Member

Откуда:
Сообщений: 15330
joe_satirus
Я правильно понял?
главное чтобы ты понял, что ни в одной серьезной системе вопрос о борьбе с ветряными мутациями даже на горизонте не появляется.
16 окт 14, 23:22    [16717420]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
-2-,

Хорошо жить в идеальном мире:)
17 окт 14, 11:56    [16719346]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
Запощу сюда рабочий вариант, а то сам часто читал ветки, где вроде ответили и автор понял, но что именно он понял, неясно
Итак, что у меня получилось:
CREATE OR REPLACE TRIGGER tr_pre_bre_instal_compound
  FOR INSERT OR UPDATE OR DELETE ON premature_breach_instalments
    COMPOUND TRIGGER

  -- Global declaration.
  
   out_status_code          NUMBER (4) := 0;
   out_status_description   VARCHAR2 (255) := NULL;
   
   TYPE t_change_tab IS TABLE OF SAKER.SAKSNR%TYPE;
   g_change_tab  t_change_tab := t_change_tab();

   
  
  BEFORE EACH ROW IS
  BEGIN
    
   IF INSERTING THEN
      :new.date_created := db_pink_common.fu_sysdate;

      :new.ins_pgm      := TRIM ( :new.ins_pgm);
   END IF;

   IF :new.due_date < pa_constants.c_null_date THEN
      :new.due_date := NULL;
   END IF;

   :new.user_id                      := db_pink_common.fu_getuser;
   :new.date_changed                 := db_pink_common.fu_sysdate;

   :new.total_instalment_amount      := NVL (:new.instalment_amount, 0) + NVL (:new.interests, 0) + NVL (:new.penalty_interests, 0)
                                        + NVL (:new.expenses, 0) + NVL (:new.unspecified_amount, 0);
    
  END BEFORE EACH ROW;

  AFTER EACH ROW IS
  BEGIN
    g_change_tab.extend;
    g_change_tab(g_change_tab.last)      := :new.case_no;
  END AFTER EACH ROW;
  
  AFTER STATEMENT IS
  BEGIN
    FOR i IN g_change_tab.first .. g_change_tab.last LOOP
      pa_premature_breach.pr_upd_amount_next_inst (
      in_case_no        => g_change_tab(i)--:new.case_no
     ,out_status        => out_status_code
     ,out_status_desc   => out_status_description);

      IF out_status_code < 0 THEN
       raise_application_error (
         -20000
        ,'Error during call to PA_PREMATURE_BREACH.PR_UPD_AMOUNT_NEXT_INST: ' || out_status_description);
      END IF;
    END LOOP;
    g_change_tab.delete;--or trancate
  END AFTER STATEMENT;
  

END tr_pre_bre_instal_compound;


Прошу улучшать.
17 окт 14, 12:29    [16719731]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
-2-
Member

Откуда:
Сообщений: 15330
joe_satirus
рабочий вариант
проверено в идеальных условиях?
17 окт 14, 12:35    [16719798]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
-2-,

В приближенных к идеальным:)
17 окт 14, 13:28    [16720440]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 242
joe_satirus,

1. При delete проверь.
2. На случай рекурсии в pa_premature_breach.pr_upd_amount_next_inst (если там есть операторы dml по premature_breach_instalments) тоже.
17 окт 14, 20:24    [16723224]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
joe_satirus
Member

Откуда:
Сообщений: 63
Да ну,

да, ON DELETE было лишним...
12 ноя 14, 19:14    [16836515]     Ответить | Цитировать Сообщить модератору
 Re: ORA-04091: table TABLE_NAME is mutating, trigger/function may not see it  [new]
alex-ls
Member

Откуда: Иркутская обл - Пенза - Москва
Сообщений: 6910
тебе концепции надо почитать, твой вопрос - это простейший случай. смешно его задавать на форуме, когда ответ на него есть в любой книжке/форуме
13 ноя 14, 04:50    [16837604]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить