Ошибка возникает, поскольку таблица, для которой определен триггер, также запрашивается в триггере. Одним из решений проблемы является использование прагмы автономной транзакции и перемещение логики триггера в процедуру, которая использует эту прагму, и вызов этой процедуры в триггере.
В моей системе мне удалось воспроизвести ошибку, а также проверить, работает ли приведенное ниже решение:
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