• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

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

    发布者: 福建二哥 | 发布时间: 2025-6-18 09:27| 查看数: 24| 评论数: 0|帖子模式

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


    首先TRIGGER基本语句
    1. create or replace trigger 'trigger_name'--触发器名称
    2. before insert --或 after insert (触发时机)
    3. --关键字before和after用于标识触发时间,顾名思义,before代表触发器里面的命令在DML修改数据之前执行,
    4. --after代表触发器里面的命令在DML修改数据之后执行。
    5. REFERENCING new as new --或old as old (用于触发器中参数使用)
    6. --注:before中的new指的是当前插入的集,after中的old指的是当前插入的集
    7. FOR EACH ROW --指当前触发器为行级触发器(行级触发器相对于语句级触发器)
    8. --行级触发器能够通过 :new.属性 和 :old.属性等获得update或者insert发生之前的新值和发生值之后的旧值。
    9. declare --声明变量……
    10. BEGIN
    11. END;
    复制代码
    关于行级触发器的 :new.属性 和 ld.属性使用
    1. TRIGGER TONGBUJIAYI_SFZH
    2. before
    3. DELETE OR UPDATE of D_SFZH
    4. ON T_DA_JKDA_RKXZL
    5. REFERENCING NEW AS NEW OLD AS OLD
    6. FOR EACH ROW
    7. BEGIN
    8. IF UPDATING
    9. THEN
    10. insert into T_DA_JKDA_RKXZL_GWANDJY(ID,D_GRDABH,P_RGID,D_SFZH,D_SFZHXGQ,D_DATZXGH,D_XM,D_BGSJ,D_BGZT)
    11. VALUES (SYS_GUID(),:OLD.D_GRDABH,:OLD.P_RGID,:OLD.D_SFZH,:NEW.D_SFZH,'',:OLD.D_XM,sysdate,'2');
    12. ELSIF DELETING
    13. THEN
    14. insert into T_DA_JKDA_RKXZL_GWANDJY(ID,D_GRDABH,P_RGID,D_SFZH,D_SFZHXGQ,D_DATZXGH,D_XM,D_BGSJ,D_BGZT)
    15. VALUES (SYS_GUID(),:OLD.D_GRDABH,:OLD.P_RGID,:OLD.D_SFZH,'','',:OLD.D_XM,sysdate,'1');
    16. END IF;
    17. END;
    复制代码
    在Oracle中执行DML语句的时候是需要显示进行提交操作的。
    当我们进行插入的时候,会触发触发器执行对触发器作用表和扩展表的种种操作,
    但是这个时候触发器和插入语句是在同一个事务管理中的,因此在插入语句没有被提交的情况下,我们无法对触发器作用表进行其他额外的操作。
    如果执行其他额外的操作则会抛出如下异常信息。
    1. ORA-04091:表*****发生了变化触发器/函数不能读它
    复制代码
    此次触发器产生场景:
    一个身份证号及个人信息导入到系统中,在系统中修改了关于疫情的信息。
    但再次导入此人的信息时(每次导入的信息都不包含关于疫情的信息),则需要同步。
    由此引入触发器,触发条件为insert
    1. TRIGGER DETECTION_USERS_SYN_VACCINE
    2.   BEFORE INSERT ON DETECTION_USERS
    3.   REFERENCING new as new
    4.   FOR EACH ROW

    5. DECLARE --oracle中声明多个属性时只需要用一次DECLARE即可
    6.   V_ID              DETECTION_USERS.ID%TYPE;--此处声明的属性是按照DETECTION_USERS表中的属性声明
    7.   V_IS_VACCINATION  DETECTION_USERS.IS_VACCINATION%TYPE;
    8.   V_VACCINE1        DETECTION_USERS.VACCINE1%TYPE;
    9.   V_VACCINE2        DETECTION_USERS.VACCINE2%TYPE;
    10.   V_VACCINE3        DETECTION_USERS.VACCINE3%TYPE;
    11.   V_NUM_VACCINATION DETECTION_USERS.NUM_VACCINATION%TYPE;
    12.   --声明游标查询此人添加之前的接种信息
    13.   CURSOR latests is
    14.     SELECT ID,
    15.            IS_VACCINATION,
    16.            VACCINE1,
    17.            VACCINE2,
    18.            VACCINE3,
    19.            NUM_VACCINATION
    20.       FROM (SELECT t.*, row_number() over(order by nvl(zdrq, '0') DESC) rn
    21.               from (SELECT *
    22.                       FROM (SELECT ID,
    23.                                    IS_VACCINATION,
    24.                                    VACCINE1,
    25.                                    VACCINE2,
    26.                                    VACCINE3,
    27.                                    NUM_VACCINATION,
    28.                                    (CASE
    29.                                      WHEN (VACCINE3 IS NOT null) THEN
    30.                                       VACCINE3
    31.                                      WHEN (VACCINE2 IS NOT null) THEN
    32.                                       VACCINE2
    33.                                      WHEN (VACCINE1 IS NOT null) THEN
    34.                                       VACCINE1
    35.                                      ELSE
    36.                                       ''
    37.                                    END) AS zdrq
    38.                               FROM DETECTION_USERS
    39.                              WHERE "IDENTITY" = :new."IDENTITY"
    40.                                AND IS_VACCINATION IS NOT NULL)) t)
    41.      WHERE rn = 1;
    42. BEGIN

    43.   OPEN latests;
    44.   FETCH latests
    45.     INTO V_ID,
    46.          V_IS_VACCINATION,
    47.          V_VACCINE1,
    48.          V_VACCINE2,
    49.          V_VACCINE3,
    50.          V_NUM_VACCINATION;
    51.          ---打印语句
    52. --  DBMS_OUTPUT.PUT_LINE('latests===' || V_ID || '**' || V_IS_VACCINATION || '**' ||
    53. --                       V_VACCINE1 || '**' || V_VACCINE2 || '**' ||
    54. --                       V_VACCINE3 || '**' || V_NUM_VACCINATION);
    55. --  DBMS_OUTPUT.PUT_LINE('new===' || :new.ID || '**' || :new.IS_VACCINATION || '**' ||
    56. --                       :new.VACCINE1 || '**' || :new.VACCINE2 || '**' ||
    57. --                       :new.VACCINE3 || '**' || :new.NUM_VACCINATION);

    58.   IF INSERTING THEN
    59.     :new.IS_VACCINATION  := V_IS_VACCINATION;--将打开的cursor赋值到新插入的这列数值中
    60.     :new.VACCINE1        := V_VACCINE1;
    61.     :new.VACCINE2        := V_VACCINE2;
    62.     :new.VACCINE3        := V_VACCINE3;
    63.     :new.NUM_VACCINATION := V_NUM_VACCINATION;
    64.   
    65.   END IF;
    66.   --FETCH NEXT FROM from_inserted INTOV_ID,V_IS_VACCINATION,V_VACCINE1,V_VACCINE2, V_VACCINE3,V_NUM_VACCINATION;
    67.   --循环,此处cursor只有一条,不需要。
    68.   CLOSE latests;

    69. END;
    复制代码
    总结

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

    来源:https://www.jb51.net/database/328820woz.htm
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表