oracle 使用触发器更新表-如何解决突变错误

a14dhokn  于 2022-11-03  发布在  Oracle
关注(0)|答案(2)|浏览(208)

我正在尝试创建一个触发器,以便在创建或更新记录后更新记录的某些列。
有我的代码:

CREATE OR REPLACE TRIGGER "TRIGGER_UPDATE_CONTRACTOR_LOT"
AFTER INSERT OR UPDATE ON "CONTRACTOR_LOT"
FOR EACH ROW
DECLARE
    CONTRACT_LOT_LABEL VARCHAR2(255 BYTE);
    CONTRACTOR_LABEL VARCHAR2(200 BYTE);
BEGIN

       SELECT LABEL INTO CONTRACT_LOT_LABEL FROM LOT_T WHERE ID = :NEW.LOT_ID;
       SELECT CONTRACTOR INTO CONTRACTOR_LABEL FROM CONTRACTOR_T WHERE ID = :NEW.CONTRACTOR_ID;

       UPDATE CONTRACTOR_LOT
        SET LABEL = CONTRACT_LOT_LABEL  || ':' || CONTRACTOR_LABEL,
            FRAMEWORK_CONTRACT_NUMBER_LABEL = :NEW.ORDER || ':' || CONTRACT_LOT_LABEL  || :NEW.FRAMEWORK_CONTRACT_NUMBER
        WHERE ID = :NEW.ID;  
END;

我收到错误ORA-04091(突变)我尝试添加PRAGMA AUTONOMOUS_TRANSACTION;,但收到错误ORA-00060(等待资源时检测到死锁),因此我在更新后添加了COMMIT;,但问题仍然相同。
你能帮我拿一下吗?

tzdcorbm

tzdcorbm1#

您不能在触发器中的父表上执行DML,而且实际上很少有任何理由这样做。尝试这样做,使用BEFORE触发器,并且只修改激发该触发器的现有INSERTUPDATENEW值:

CREATE OR REPLACE TRIGGER TRIGGER_UPDATE_CONTRACTOR_LOT
BEFORE INSERT OR UPDATE ON CONTRACTOR_LOT
FOR EACH ROW
DECLARE
    CONTRACT_LOT_LABEL VARCHAR2(255 BYTE);
    CONTRACTOR_LABEL VARCHAR2(200 BYTE);
BEGIN
    SELECT LABEL INTO CONTRACT_LOT_LABEL FROM LOT_T WHERE ID = :NEW.LOT_ID;
    SELECT CONTRACTOR INTO CONTRACTOR_LABEL FROM CONTRACTOR_T WHERE ID = :NEW.CONTRACTOR_ID;

    :NEW.CONTRACTOR_LOT := CONTRACT_LOT_LABEL  || ':' || CONTRACTOR_LABEL;
    :NEW.FRAMEWORK_CONTRACT_NUMBER_LABEL := :NEW.ORDER || ':' || CONTRACT_LOT_LABEL  || :NEW.FRAMEWORK_CONTRACT_NUMBER;
END;
envsm3lx

envsm3lx2#

您的触发器正在捕获此表上的更改和插入,然后在同一表上进行更新。这似乎是一个恶性循环。因为触发器内部的更新也将需要启动此触发器

相关问题