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

Joh*_*ust 1 sql oracle triggers unique-constraint

我想写在表上插入前检查,看是否有在该表中现有条目具有相同的触发器fk_idactive flag.例如,想象下表:

| row_id | fk_id |  active_flag |
| ------------------------------|
|    1   |   500 |         1    |
|    2   |   500 |         0    |
|    3   |   501 |         1    |
Run Code Online (Sandbox Code Playgroud)

假设我想用fk_id = 500和插入一个新行active_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;
/
Run Code Online (Sandbox Code Playgroud)

使用此触发器,它在插入时完全正常,但是当我进行更新时,我得到一个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 '
Run Code Online (Sandbox Code Playgroud)

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

我该如何实施这样的支票?

Ton*_*ews 6

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

create unique index myindex on mytable (case when active_flag=1 then fk_id end);
Run Code Online (Sandbox Code Playgroud)

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