OracleDB:触发表以检查自循环/循环

时间:2014-01-02 11:48:50

标签: java sql oracle triggers

我有这个表“function”,其中fk为自身(1:N),我需要检查行是否有一些坏循环。 我的想法是创建一个类似这样的触发器:

create or replace trigger FNZ_CHECK_PARENT after insert or update on FUNZIONE
   For Each Row
   Declare
    cnt number;
     Begin
       Select CONNECT_BY_ISCYCLE "is_cycle"
        Into cnt
       From Funzione
        Where Fnz_Parent Is Not Null 
        Connect By Nocycle Prior fnz_id = fnz_parent;

        if cnt > 0
        Then Raise_Application_Error(-20000, 'this is not allowed');
        end if;
    End;

但它不会出现此错误:

Errore SQL: ORA-04091: La tabella ACCERTA.FUNZIONE è in fase di modifica, il trigger/funzione non può leggerla
ORA-06512: a "ACCERTA.FNZ_CHECK_PARENT", line 4
ORA-04088: errore durante esecuzione del trigger 'ACCERTA.FNZ_CHECK_PARENT'
04091. 00000 -  "table %s.%s is mutating, trigger/function may not see it"
*Cause:    A trigger (or a user defined plsql function that is referenced in
           this statement) attempted to look at (or modify) a table that was
           in the middle of being modified by the statement which fired it.
*Action:   Rewrite the trigger (or function) so it does not read that table.

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

FOR EACH ROW触发器无法访问其定义的表。这就是Oracle的方式。

您可以做的是:在没有触发器的情况下插入行,然后对循环执行AFTER STATEMENT触发器检查。

或者,您可以使用存储过程,而不是直接插入。当然,只有在你可以控制主叫方时才有效。

另一个想法是创建一个视图并制作一个“INSTEAD OF TRIGGER”,尽管如果它真的有效,我从未尝试过。

答案 1 :(得分:0)

这是尝试更改可变表。 Oracle(至少11.1)不允许这样做。 一个路由可以是触发器中的自治事务编译指示。另一个是在约束中实现这个逻辑(无论它是什么,因为你没有提供示例),oracle就是这样的。 在任何情况下,你的问题都是模棱两可的。