oracle中变异表处理办法

变异表

   在数据库中,变异表是当前被DML语句修改的表。

  而对于数据库上的triggrt(触发器)来说,变异表就是trigger在其上定义的表。
  需要明确的是trigger中SQL语句不能进行如下操作:
  1)读或者修改触发语句的任何变异表,包括触发表本身。
  2)读或者修改触发表的约束表中的主关键字,唯一关键字和外部关键字。
  而除此之外的其他列都可以修改。
  如何突破变异表?
  方法一是用两个触发器,一个行级的,一个语句级的(速度快,推荐!)
  方法二是用dbms_job.run包(但运行的时间过长,2秒左右)
  方法三是可以使用AutoCommit方法解决(但破坏了事务的一致性,多数情况下是错误的)。

下面是包 + 行级触发器 + 语句级触发器的实例:

在使用Oracle行级触发器时,如果需要对本表进行DML操作(包括select),一般都会报错:

ORA-04091: 表 /**TABLENAME**/ 发生了变化,触发器/函数不能读···

一般可以使用“ 包 + 行级触发器 + 语句级触发器 ”组合使用来解决。

// 创建包

CREATE OR REPLACE PACKAGE BRPMS.FXYDATA AS
  TYPE T_COL1 IS TABLE OF BRPMS.TB_RISK_FXY.GUID%TYPE INDEX BY BINARY_INTEGER;
  V_GUID T_COL1;
  V_ROW  BINARY_INTEGER := 0;
END;

// 创建行级触发器

CREATE OR REPLACE TRIGGER BRPMS.T_IFFXYMODIFIED
  BEFORE UPDATE OF FXFXJDON BRPMS.TB_RISK_FXY
  FOR EACH ROW
BEGIN
  IF :NEW.JHLX = '1' THEN
    IF :NEW.FXFXJD = '已发布' THEN
      BRPMS.FXYDATA.V_ROW  := BRPMS.FXYDATA.V_ROW + 1;
      BRPMS.FXYDATA.V_GUID(BRPMS.FXYDATA.V_ROW) := :NEW.GUID;
    END IF;
  END IF;
END;


// 创建语句级触发器

CREATE OR REPLACE TRIGGER BRPMS.T_COPY_Y2R
  AFTER UPDATE OF FXFXJD ON BRPMS.TB_RISK_FXY
DECLARE
  S_YJHID BRPMS.TB_RISK_FXY.GUID%TYPE;
  S_RJHID BRPMS.TB_RISK_FXY.GUID%TYPE;
BEGIN
  FOR V_LOOP IN 1 .. BRPMS.FXYDATA.V_ROW LOOP
    S_YJHID := BRPMS.FXYDATA.V_GUID(V_LOOP);
    SELECT (SELECT F.GUID FROM BRPMS.TB_RISK_FXY F WHERE F.TDJH_ID = R.GUID)
      INTO S_RJHID
      FROM (SELECT * FROM BRPMS.TB_RISK_TDJH WHERE JHLX = 1) Y,
           (SELECT * FROM BRPMS.TB_RISK_TDJH WHERE JHLX = 2) R
     WHERE Y.YXTJHBH = R.YJHZJ
       AND EXISTS
     (SELECT FXY.GUID
              FROM BRPMS.TB_RISK_FXY FXY
             WHERE FXY.TDJH_ID = R.GUID)
       AND Y.GUID =
           (SELECT F.TDJH_ID FROM BRPMS.TB_RISK_FXY F WHERE F.GUID = S_YJHID)
       AND ROWNUM = 1;
    IF S_RJHID IS NOT NULL THEN
      BRPMS.P_COPY_Y2R_MANUAL(S_YJHID, S_RJHID);
    END IF;
  END LOOP;
END;


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值