Oracle - 在触发器中获取变异表异常?

时间:2016-08-16 20:03:03

标签: sql oracle triggers unique-constraint

我想编写一个触发器,在插入表之前进行检查,以查看该表中是否存在具有相同fk_idactive flag的现有条目。例如,想象下表:

| row_id | fk_id |  active_flag |
| ------------------------------|
|    1   |   500 |         1    |
|    2   |   500 |         0    |
|    3   |   501 |         1    |

我想要插入一个包含fk_id = 500active_flag = 1的新行。我想对此抛出异常,因为根据我的规则,在任何给定时间,您不能在此表中拥有两个具有相同fk_id活动的行。

我写了一个触发器来尝试处理这个问题:

CREATE OR REPLACE TRIGGER MYSCHEMA.CHECK_DUPS_BIU

BEFORE INSERT OR UPDATE ON MYSCHEMA.MYTABLE_T FOR EACH ROW
DECLARE
    l_cnt NUMBER;
    e_dup EXCEPTION;
BEGIN

    SELECT COUNT(*)
    INTO l_cnt
    FROM MYSCHEMA.MYTABLE_T 
    WHERE fk_id = :new.fk_id
    AND active_flag > 0;

    IF(l_cnt > 0)
    THEN
        RAISE e_dup;
    END IF;

EXCEPTION 
 WHEN e_dup THEN
  raise_application_error(-20300, 'You cannot insert two active items with the same fk_id');
END CHECK_DUPS_BIU;
/

使用此触发器,它在插入时完全正常,但是当我进行更新时,我得到一个Mutating表异常:

ORA-04091: table MYSCHEMA.CHECK_DUPS_BIU is mutating, trigger/function may not see it
ORA-06512: at "MYSCHEMA.CHECK_DUPS_BIU ", line 12
ORA-04088: error during execution of trigger 'MYSCHEMA.CHECK_DUPS_BIU '

我对这个问题进行了一些研究,我读到处理这种情况的更好方法*可能是使用约束而不是我不知道如何编写这样一个检查另一列的约束( active_flag)。

我该如何实施这样的检查?

1 个答案:

答案 0 :(得分:6)

不要使用触发器,使用基于UNIQUE函数的索引:

create unique index myindex on mytable (case when active_flag=1 then fk_id end);

当active_flag不为1时,索引中不会存储任何条目;当active_flag为1时,将存储一个条目 - 但如果已存在相同的fk_id,则会引发异常。