【问题标题】:Oracle trigger error ORA-04091Oracle 触发器错误 ORA-04091
【发布时间】:2018-11-30 16:02:57
【问题描述】:

执行我的触发器时出现错误(ORA-04091:表 DBPROJEKT_AKTIENDEPOT.AKTIE 正在变异,触发器/函数可能看不到它):

CREATE OR REPLACE TRIGGER Aktien_Bilanz_Berechnung
AFTER 
INSERT OR UPDATE OF  TAGESKURS
OR INSERT OR UPDATE OF  WERT_BEIM_EINKAUF
ON AKTIE
FOR EACH ROW
DECLARE
bfr number;
Begin
bfr := :new.TAGESKURS - :new.WERT_BEIM_EINKAUF;
UPDATE AKTIE
SET BILANZ = TAGESKURS - WERT_BEIM_EINKAUF;
IF bfr < -50
THEN
DBMS_OUTPUT.PUT_LINE('ACHTUNG: The value (Nr: '||:new.AKTIEN_NR||') is very low!');
END IF;
END;

我想在计算后检查值“BILANZ”,它是否低于-50。 你知道为什么会抛出这个错误吗?

感谢您的帮助!

【问题讨论】:

    标签: sql oracle triggers database-trigger


    【解决方案1】:

    您正在使用触发器修改表。使用before update 触发器:

    CREATE OR REPLACE TRIGGER Aktien_Bilanz_Berechnung
    BEFORE INSERT OR UPDATE OF TAGESKURS OR INSERT OR UPDATE OF  WERT_BEIM_EINKAUF
    ON AKTIE
    FOR EACH ROW
    DECLARE
        v_bfr number;
    BEGIN
        v_bfr := :new.TAGESKURS - :new.WERT_BEIM_EINKAUF;
        :new.BILANZ := v_bfr;
        IF v_bfr < -50 THEN
          Raise_Application_Error(-20456,'ACHTUNG: The value (Nr: '|| :new.AKTIEN_NR || ') is very low!');
        END IF;
    END;
    

    【讨论】:

    • 我将dbms_output.put_line 替换为Raise_Application_Error 以便可以从任何地方看到错误,甚至可以从应用程序中看到。摆脱了无用的dual。 +1
    • @BarbarosÖzhan 。 . .那些很好。出于某种原因,当我将值分配给 Oracle 触发器中的列时,我习惯使用 into。不知道为什么。这可能是一种古老的习惯。
    【解决方案2】:

    这里有几个问题:

    1. Oracle 不允许您对在该表上定义的行触发器或从此类触发器调用的任何代码中的表执行 SELECT/INSERT/UPDATE/DELETE,这就是在运行时发生错误的原因.有一些方法可以解决这个问题——例如,你可以阅读我对this questionthis question 的回答——但通常你必须避免从触发器中访问定义了行触发器的表。

    2. 在此触发器中执行的计算称为业务逻辑,不应在触发器中执行。将诸如此类的逻辑放在触发器中,无论它看起来多么方便,最终都会让任何必须维护此代码的人感到非常困惑,因为BILANZ 的值在阅读应用程序代码的人的地方发生了变化INSERTUPDATE 语句看不到。此计算应在INSERTUPDATE 语句中执行,而不是在触发器中。定义一个对表执行 INSERT/UPDATE/DELETE 操作的过程被认为是一种很好的做法,以便可以在一个地方捕获所有此类计算,而不是分散在整个代码库中。

    3. 在 BEFORE ROW 触发器中,您可以修改 :NEW 行变量中的字段值,以便在将值写入数据库之前更改这些值。有时这是可以接受的,例如在设置列来跟踪上次更改行的时间和人员时,但总的来说这是一个坏主意。

    祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-17
      • 2015-08-03
      • 2013-05-13
      • 1970-01-01
      • 2012-04-26
      • 2017-12-15
      • 1970-01-01
      • 2015-08-06
      相关资源
      最近更新 更多