首页 文章

SQL错误:执行触发时ORA-04091

提问于
浏览
0

我正在尝试执行我的触发器:

CREATE OR REPLACE TRIGGER Trg_video_bfr_delete
    AFTER DELETE ON CMS_VIDEO
    FOR EACH ROW
DECLARE
    CODE varchar2(60);   
BEGIN
    SELECT CODE INTO CODE 
    from CMS_VIDEO 
    WHERE CODE = :OLD.CODE;
    IF CODE IS NOT NULL THEN
        INSERT INTO ASSET_DELETE_INDEX(CODE,ASSET_TYPE,IW_VPATH,LANGUAGE,MODIFIED_DTE) 
        VALUES (CODE,'Video',:old.IW_VPATH,:old.CONTENT_LANGUAGE,sysdate);
    END IF;
EXCEPTION 
    WHEN NO_DATA_FOUND THEN
        INSERT INTO ASSET_DELETE_INDEX (CODE,ASSET_TYPE,IW_VPATH,LANGUAGE,MODIFIED_DTE)
        VALUES (CODE,'Video',null,:old.CONTENT_LANGUAGE,sysdate);
        COMMIT;
END Trg_video_bfr_delete;
/

但是我在表上执行删除命令时收到以下错误

错误报告 -

SQL错误:ORA-04091:表LSDS.CMS_VIDEO正在变异,触发器/函数可能看不到它ORA-06512:在“LSDS.TRG_VIDEO_BFR_DELETE”,第6行ORA-04088:执行触发器期间出错'LSDS.TRG_VIDEO_BFR_DELETE'04091 .00000 - “表%s . %s正在变异,触发器/函数可能看不到它”*原因:触发器(或此语句中引用的用户定义的plsql函数)试图查看(或修改)表正在被解雇它的声明修改的中间 . *操作:重写触发器(或函数),使其不读取该表 .

有人可以帮忙吗?

3 回答

  • -1

    你写了触发器 AFTER DELETE ON CMS_VIDEO . 从 CMS_VIDEO 表执行 DELETE 时,将触发此触发器 . 因此,在修改 CMS_VIDEO 表时,您无法在任何触发器,过程或函数中修改或查询同一个表 .

    CREATE OR REPLACE TRIGGER Trg_video_bfr_delete
    AFTER DELETE ON CMS_VIDEO
    FOR EACH ROW
    
    BEGIN
      IF :old.CODE IS NOT NULL THEN
        INSERT INTO ASSET_DELETE_INDEX(CODE, ASSET_TYPE, IW_VPATH, LANGUAGE, MODIFIED_DTE)
        VALUES (:old.CODE, 'Video', :old.IW_VPATH, :old.CONTENT_LANGUAGE, sysdate);
      END IF;
    END Trg_video_bfr_delete;
    /
    
  • 0

    这是因为您正在从表中删除记录,同一个表用作触发器内的引用 . 这是“变异错误”的情况 . 您应该切换到语句级触发器它是否符合您的要求,或者您可以使用具有多个入口点并且能够处理此类场景的复合触发器 .

    请参考https://oracle-base.com/articles/9i/mutating-table-exceptions

  • 2

    根据提供的代码片段,我没有看到在变异 TABLE 上做任何一点 SELECT . 我们可以很容易地获取该值 . 希望下面片段有帮助 .

    CREATE OR REPLACE TRIGGER Trg_video_bfr_delete AFTER
      DELETE ON CMS_VIDEO FOR EACH ROW 
    --  DECLARE CODE VARCHAR2(60);
      BEGIN
    --    SELECT CODE INTO CODE FROM CMS_VIDEO WHERE CODE = :OLD.CODE;
        IF CODE IS NOT NULL THEN
          INSERT
          INTO ASSET_DELETE_INDEX
            (
              CODE,
              ASSET_TYPE,
              IW_VPATH,
              LANGUAGE,
              MODIFIED_DTE
            )
            VALUES
            (
              :old.code,
              'Video',
              :old.IW_VPATH,
              :old.CONTENT_LANGUAGE,
              sysdate
            );
        END IF;
      EXCEPTION
      WHEN OTHERS THEN
        INSERT
        INTO ASSET_DELETE_INDEX
          (
            CODE,
            ASSET_TYPE,
            IW_VPATH,
            LANGUAGE,
            MODIFIED_DTE
          )
          VALUES
          (
            :old.code,
            'Video',
            NULL,
            :old.CONTENT_LANGUAGE,
            sysdate
          );
        COMMIT;
      END Trg_video_bfr_delete;
    

相关问题