oracle 触发器 ORA-04091

Posted

技术标签:

【中文标题】oracle 触发器 ORA-04091【英文标题】:oracle trigger ORA-04091 【发布时间】:2016-07-04 16:09:43 【问题描述】:

我已经创建了一个监视一张桌子的触发器。当用户将 Candidate_selected 列更改为 Y 时,我希望 oracle 从该表中提取列并将它们插入到一个查找表中,该表跟踪当前处于活动状态的候选者,即 ='Y'。 当我尝试更新该列时,我收到错误 ORA-04091。触发器不会更改构建它的表,我不知道为什么会出现此错误。 任何帮助将不胜感激 - 我去过几个网站但看不到修复,我想我已经盯着它太久了:)

CREATE OR REPLACE TRIGGER DEMO_SCHEMA.TRG_CANDIDATE_SELECTED
AFTER UPDATE OF CANDIDATE_SELECTED ON DEMO_SCHEMA.TBL_CANDIDATES FOR EACH ROW
BEGIN

    IF :NEW.CANDIDATE_SELECTED = 'Y' THEN

        INSERT INTO DEMO_SCHEMA.TBL_CANDIDATES_LKP 
            (UPDATED_DT, GROUP_ID, CAND_ID
            ,STAGE, STEP, EQUIPMENT, ORDER_REQ
            ,INCLUDED_IN_STUDY)
        SELECT SYSDATE, GROUP_ID, CAND_ID, STAGE
                    ,STEP, TRIM(REGEXP_SUBSTR(EQUIPMENT, '[^,]+', 1, LEVEL)) EQUIPMENT
                    ,(CASE WHEN UPPER(ORDER_REQ) = 'FALSE' THEN 1
                                 ELSE ROW_NUMBER() OVER (PARTITION BY GROUP_ID, CAND_ID, STAGE, STEP ORDER BY CAND_ID)
                        END)  ORDER_REQ, INCLUDED_IN_STUDY
        FROM (
            SELECT GROUP_ID, CAND_ID
                       ,STAGE, STEP, EQUIPMENT, EQUIPMENT EQUIP
                       ,ORDER_REQ, INCLUDED_IN_STUDY
            FROM DEMO_SCHEMA.TBL_CANDIDATES
            WHERE GROUP_ID = :NEW.GROUP_ID
            AND LOT_ID = :NEW.CAND_ID
            AND STAGE = :NEW.STAGE
            AND STEP = :NEW.STEP
            )    
        CONNECT BY LEVEL <= REGEXP_COUNT(EQUIP,', ')+1;

    ElSIF :NEW.CANDIDATE_SELECTED = 'N' THEN

        UPDATE DEMO_SCHEMA.TBL_CANDIDATE_LKP
        SET INCLUDED_IN_STUDY = :NEW.CANDIDATE_SELECTED
        WHERE GROUP_ID = :NEW.GROUP_ID
        AND CAND_ID = :NEW.CAND_ID
        AND STAGE = :NEW.STAGE
        AND STEP = :NEW.STEP;

    END IF;

END TRG_CANDIDATE_SELECTED;
/

那里可能存在语法错误,但那是因为我在发布之前必须更改一些内容。此代码确实在 Oracle 中编译。 干杯。

【问题讨论】:

“ORA-04091”属于什么错误信息?请在错误编号旁边提供完整的错误消息;我们并不是所有关于 Oracle 错误编号及其相应错误消息的百科全书! *:-) tbl_candidates 上的行级触发器通常不允许查询tbl_candidates。不知道你的数据模型,你真的需要查询tbl_candidates 还是只使用:new 伪记录中已经存在的数据? @JustinCave 但是插入语句中的 tbl_candidates 与触发器打开的 tbl_candidates 的架构不同,假设 OP 没有在他们的示例代码中打错字。 @Boneist - 我假设这是“我在发布之前必须更改一些内容”评论的一部分。我猜它们是同一张表,并且修改了两个架构引用之一。 @JustinCave *:-) 我应该知道不要相信问题所说的! *;-) 【参考方案1】:

正如 Justin Cave 所建议的,您的问题是您从触发器所属的同一个表中进行选择。

如果由于需要在 EQUIPMENT 列中的每个项目有一行而需要将其保留为 insert as select 语句,那么您可以从 dual 中选择新值,如下所示:

CREATE OR REPLACE TRIGGER DEMO_SCHEMA.TRG_CANDIDATE_SELECTED
AFTER UPDATE OF CANDIDATE_SELECTED ON DEMO_SCHEMA.TBL_CANDIDATES FOR EACH ROW
BEGIN

    IF :NEW.CANDIDATE_SELECTED = 'Y' THEN

        INSERT INTO DEMO_SCHEMA.TBL_CANDIDATES_LKP 
            (UPDATED_DT, GROUP_ID, CAND_ID
            ,STAGE, STEP, EQUIPMENT, ORDER_REQ
            ,INCLUDED_IN_STUDY)
        SELECT SYSDATE, GROUP_ID, CAND_ID, STAGE
                    ,STEP, TRIM(REGEXP_SUBSTR(EQUIPMENT, '[^,]+', 1, LEVEL)) EQUIPMENT
                    ,(CASE WHEN UPPER(ORDER_REQ) = 'FALSE' THEN 1
                                 ELSE ROW_NUMBER() OVER (PARTITION BY GROUP_ID, CAND_ID, STAGE, STEP ORDER BY CAND_ID)
                        END)  ORDER_REQ, INCLUDED_IN_STUDY
        FROM (
            SELECT :NEW.GROUP_ID group_id,
                   :NEW.CAND_ID cand_id,
                   :NEW.STAGE stage,
                   :NEW.STEP step,
                   :NEW.EQUIPMENT equipment,
                   :NEW.EQUIPMENT EQUIP,
                   :NEW.ORDER_REQ order_req,
                   :NEW.INCLUDED_IN_STUDY included_in_study
            FROM dual
            )    
        CONNECT BY LEVEL <= REGEXP_COUNT(EQUIP,', ')+1;

    ElSIF :NEW.CANDIDATE_SELECTED = 'N' THEN

        UPDATE DEMO_SCHEMA.TBL_CANDIDATE_LKP
        SET INCLUDED_IN_STUDY = :NEW.CANDIDATE_SELECTED
        WHERE GROUP_ID = :NEW.GROUP_ID
        AND CAND_ID = :NEW.CAND_ID
        AND STAGE = :NEW.STAGE
        AND STEP = :NEW.STEP;

    END IF;

END TRG_CANDIDATE_SELECTED;
/

【讨论】:

非常感谢 - 我会试一试

以上是关于oracle 触发器 ORA-04091的主要内容,如果未能解决你的问题,请参考以下文章

如何在Oracle触发器中使用查询语句

仅在 old = new 上进行选择时获取变异表 (ORA-04091)

ORA-04091“更新后”触发器错误,如何解决?

ORA-04091 由于游标,表名在触发器中发生变化

ORA-04091: 表 [blah] 正在变异,触发器/函数可能看不到它

ORA-04091: 表 JOSEP.EMP 正在变异,触发器/函数可能看不到它