欢迎投稿

今日深度:

Oracle使用insert触发器遇到的问题及解决,

Oracle使用insert触发器遇到的问题及解决,


目录
  • Oracle使用insert触发器遇到的问题
    • 首先TRIGGER基本语句
    • 关于行级触发器的 :new.属性 和 :old.属性使用
  • 总结

    Oracle使用insert触发器遇到的问题

    首先TRIGGER基本语句

    create or replace trigger 'trigger_name'--触发器名称
    before insert --或 after insert (触发时机)
    --关键字before和after用于标识触发时间,顾名思义,before代表触发器里面的命令在DML修改数据之前执行,
    --after代表触发器里面的命令在DML修改数据之后执行。
    REFERENCING new as new --或old as old (用于触发器中参数使用)
    --注:before中的new指的是当前插入的集,after中的old指的是当前插入的集
    FOR EACH ROW --指当前触发器为行级触发器(行级触发器相对于语句级触发器)
    --行级触发器能够通过 :new.属性 和 :old.属性等获得update或者insert发生之前的新值和发生值之后的旧值。
    declare --声明变量……
    BEGIN
    END;

    关于行级触发器的 :new.属性 和 :old.属性使用

    TRIGGER TONGBUJIAYI_SFZH
    before
     DELETE OR UPDATE of D_SFZH
     ON T_DA_JKDA_RKXZL
    REFERENCING NEW AS NEW OLD AS OLD
     FOR EACH ROW
    BEGIN
     IF UPDATING
     THEN
    insert into T_DA_JKDA_RKXZL_GWANDJY(ID,D_GRDABH,P_RGID,D_SFZH,D_SFZHXGQ,D_DATZXGH,D_XM,D_BGSJ,D_BGZT)
    VALUES (SYS_GUID(),:OLD.D_GRDABH,:OLD.P_RGID,:OLD.D_SFZH,:NEW.D_SFZH,'',:OLD.D_XM,sysdate,'2');
    ELSIF DELETING
     THEN
    insert into T_DA_JKDA_RKXZL_GWANDJY(ID,D_GRDABH,P_RGID,D_SFZH,D_SFZHXGQ,D_DATZXGH,D_XM,D_BGSJ,D_BGZT)
    VALUES (SYS_GUID(),:OLD.D_GRDABH,:OLD.P_RGID,:OLD.D_SFZH,'','',:OLD.D_XM,sysdate,'1');
    END IF;
    END;

    在Oracle中执行DML语句的时候是需要显示进行提交操作的。

    当我们进行插入的时候,会触发触发器执行对触发器作用表和扩展表的种种操作,

    但是这个时候触发器和插入语句是在同一个事务管理中的,因此在插入语句没有被提交的情况下,我们无法对触发器作用表进行其他额外的操作。

    如果执行其他额外的操作则会抛出如下异常信息。

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

    此次触发器产生场景:

    一个身份证号及个人信息导入到系统中,在系统中修改了关于疫情的信息。

    但再次导入此人的信息时(每次导入的信息都不包含关于疫情的信息),则需要同步。

    由此引入触发器,触发条件为insert

    TRIGGER DETECTION_USERS_SYN_VACCINE
      BEFORE INSERT ON DETECTION_USERS
      REFERENCING new as new
      FOR EACH ROW
    
    DECLARE --oracle中声明多个属性时只需要用一次DECLARE即可
      V_ID              DETECTION_USERS.ID%TYPE;--此处声明的属性是按照DETECTION_USERS表中的属性声明
      V_IS_VACCINATION  DETECTION_USERS.IS_VACCINATION%TYPE;
      V_VACCINE1        DETECTION_USERS.VACCINE1%TYPE;
      V_VACCINE2        DETECTION_USERS.VACCINE2%TYPE;
      V_VACCINE3        DETECTION_USERS.VACCINE3%TYPE;
      V_NUM_VACCINATION DETECTION_USERS.NUM_VACCINATION%TYPE;
      --声明游标查询此人添加之前的接种信息
      CURSOR latests is
        SELECT ID,
               IS_VACCINATION,
               VACCINE1,
               VACCINE2,
               VACCINE3,
               NUM_VACCINATION
          FROM (SELECT t.*, row_number() over(order by nvl(zdrq, '0') DESC) rn
                  from (SELECT *
                          FROM (SELECT ID,
                                       IS_VACCINATION,
                                       VACCINE1,
                                       VACCINE2,
                                       VACCINE3,
                                       NUM_VACCINATION,
                                       (CASE
                                         WHEN (VACCINE3 IS NOT null) THEN
                                          VACCINE3
                                         WHEN (VACCINE2 IS NOT null) THEN
                                          VACCINE2
                                         WHEN (VACCINE1 IS NOT null) THEN
                                          VACCINE1
                                         ELSE
                                          ''
                                       END) AS zdrq
                                  FROM DETECTION_USERS
                                 WHERE "IDENTITY" = :new."IDENTITY"
                                   AND IS_VACCINATION IS NOT NULL)) t)
         WHERE rn = 1;
    BEGIN
    
      OPEN latests;
      FETCH latests
        INTO V_ID,
             V_IS_VACCINATION,
             V_VACCINE1,
             V_VACCINE2,
             V_VACCINE3,
             V_NUM_VACCINATION;
             ---打印语句
    --  DBMS_OUTPUT.PUT_LINE('latests===' || V_ID || '**' || V_IS_VACCINATION || '**' ||
    --                       V_VACCINE1 || '**' || V_VACCINE2 || '**' ||
    --                       V_VACCINE3 || '**' || V_NUM_VACCINATION);
    --  DBMS_OUTPUT.PUT_LINE('new===' || :new.ID || '**' || :new.IS_VACCINATION || '**' ||
    --                       :new.VACCINE1 || '**' || :new.VACCINE2 || '**' ||
    --                       :new.VACCINE3 || '**' || :new.NUM_VACCINATION);
    
      IF INSERTING THEN
        :new.IS_VACCINATION  := V_IS_VACCINATION;--将打开的cursor赋值到新插入的这列数值中
        :new.VACCINE1        := V_VACCINE1;
        :new.VACCINE2        := V_VACCINE2;
        :new.VACCINE3        := V_VACCINE3;
        :new.NUM_VACCINATION := V_NUM_VACCINATION;
      
      END IF;
      --FETCH NEXT FROM from_inserted INTOV_ID,V_IS_VACCINATION,V_VACCINE1,V_VACCINE2, V_VACCINE3,V_NUM_VACCINATION;
      --循环,此处cursor只有一条,不需要。
      CLOSE latests;
    
    END;

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持PHP之友。

    您可能感兴趣的文章:
    • Oracle数据的插入insert、更新update、删除delete、truncate举例详解
    • Oracle数据库INSERT INTO的几种用法举例
    • ORACLE如何批量插入(Insert)
    • 区别于Oracle的MySQL insert会阻塞update
    • 从Oracle数据库中读取数据自动生成INSERT语句的方法
    • Oracle如何通过表名查询触发器
    • oracle 调试触发器的基本步骤

    www.htsjk.Com true http://www.htsjk.com/oracle/48385.html NewsArticle Oracle使用insert触发器遇到的问题及解决, 目录 Oracle使用insert触发器遇到的问题 首先TRIGGER基本语句 关于行级触发器的 :new.属性 和 :old.属性使用 总结 Oracle使用insert触发器遇到的问题 首...
    评论暂时关闭