Триггер для проверки состояния - PullRequest
0 голосов
/ 29 августа 2018

У меня есть триггер в таблице t1. Если в t1 вставлена ​​какая-то плохая запись, мне нужно вставить ее в таблицу 2. Но она мутирует. Любая помощь для решения этой проблемы будет оценена.

Я использую оракул 12c.

create or replace 
TRIGGER test_air_tr
    AFTER INSERT
    ON t1 
    FOR EACH ROW

DECLARE

  v_count NUMBER;

BEGIN
--condition to check bad record. 
SELECT COUNT(*)  INTO v_count  FROM t1
     WHERE  col1=:new.col2;

IF (v_count>0) THEN 
    INSERT INTO t2
        (
          col1 ,           
          col2  )        
        VALUES
        (
         :new.col1 ,           
         :new.col2
        ) ;
END IF;

 EXCEPTION
       WHEN DUP_VAL_ON_INDEX  THEN
        UPDATE t2
            SET col2               =:new.col2

            WHERE col1       =:new.col1;
END;

1 Ответ

0 голосов
/ 29 августа 2018

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

В моей системе мне удалось воспроизвести ошибку, а также проверить, работает ли приведенное ниже решение:

SQL> desc t1
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 COL1                                               NUMBER
 COL2                                               NUMBER

(Same structure for t2 table).

CREATE OR REPLACE PROCEDURE check_bad_data (p_col1 NUMBER, p_col2 NUMBER)
IS
   PRAGMA AUTONOMOUS_TRANSACTION;
   v_cnt   NUMBER;
BEGIN
   SELECT COUNT (*)
     INTO v_cnt
     FROM t1
    WHERE col1 = p_col2;

   IF (v_cnt > 0)
   THEN
      INSERT INTO t2 (col1, col2)
           VALUES (P_col1, P_col2);
   END IF;
EXCEPTION
   WHEN DUP_VAL_ON_INDEX
   THEN
      UPDATE t2
         SET col2 = p_col2
       WHERE col1 = p_col1;
END;
/

--

create or replace 
TRIGGER test_air_tr
    AFTER INSERT
    ON t1 
    FOR EACH ROW
begin

 check_bad_data(:new.col1,:new.col2);

end;

SQL> insert into t1 values(1,2);

1 row created. 

SQL> commit;

Commit complete.

Обратите внимание, что это только одно из возможных решений, и возможны и другие способы. Я видел этот URL, который помог мне получить это решение: https://www.databasejournal.com/features/oracle/mutating-table-errorin-oraclewhyithappensand-what-you-can-doabout-it.html

- из моей системы:

SQL> delete from t1;

9 rows deleted.

SQL> delete from t2;

3 rows deleted.

SQL> commit;

Commit complete.

SQL> insert into t1 values(1,2);

1 row created.

SQL> select * from t1;

      COL1       COL2
---------- ----------
         1          2

SQL> select * from t2;

no rows selected

SQL> insert into t1 values (3,4);

1 row created.

SQL> select * from t2;

no rows selected

SQL> commit;

Commit complete.

SQL> select * from t2;

no rows selected

SQL> insert into t1 values (4,1);

1 row created.

SQL> select * from t1;

      COL1       COL2
---------- ----------
         3          4
         4          1
         1          2

SQL> select * from t2;

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