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

 更新时间:2024年10月15日 14:59:06   作者:世间所有相遇都是久别重逢  
在数据库管理中,触发器是重要的工具,用于实现自动化操作和数据完整性维护,本文以一个实际案例详解触发器的基本语句和应用,在导入个人信息时,如果已存在该信息且需更新非导入项(如疫情信息),触发器通过比较: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;

总结

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

相关文章

  • Oracle存储过程基本语法介绍

    Oracle存储过程基本语法介绍

    Oracle存储过程基本语法介绍,有需求的朋友可以参考下
    2012-11-11
  • CentOS6.2上安装Oracle10g报ins_emdb.mk错误处理方法

    CentOS6.2上安装Oracle10g报ins_emdb.mk错误处理方法

    oracle安装过程报ins_emdb.mk错误,此时继续点击“continue”即可,待Oracle完成安装后,再手工执行相应脚本完成链接即可
    2014-09-09
  • Oracle 11g下编译使用BBED的方法教程

    Oracle 11g下编译使用BBED的方法教程

    这篇文章主要给大家介绍了在Oracle 11g下编译使用BBED的方法教程,文中详细介绍了关于拷贝缺失文件、编译BBED以及BBED使用测试的相关资料,通过示例代码介绍的非常详细,需要的朋友们下面来一起看看吧。
    2017-07-07
  • Oracle表的分类以及相关参数的详解

    Oracle表的分类以及相关参数的详解

    本篇文章是对Oracle中表的分类以及相关参数进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • oracle中对JSON数据处理的详细指南

    oracle中对JSON数据处理的详细指南

    很多人对JSON不陌生,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,下面这篇文章主要给大家介绍了关于oracle中对JSON数据处理的详细指南,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-05-05
  • Oracle数据泵的导入与导出实例详解

    Oracle数据泵的导入与导出实例详解

    这篇文章主要给大家介绍了关于Oracle数据泵的导入与导出的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Oracle 数据 使用游标

    Oracle 数据 使用游标

    Oracle数据中如何使用游标的方法
    2009-06-06
  • 修改ORACLE数据库密码有效期的方法

    修改ORACLE数据库密码有效期的方法

    这篇文章主要介绍了修改ORACLE数据库密码有效期的方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-09-09
  • PLSQL配置远程Oracle数据库连接的示例代码

    PLSQL配置远程Oracle数据库连接的示例代码

    这篇文章主要介绍了PLSQL配置远程Oracle数据库连接的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Oracle使用RMAN备份数据库的流程步骤

    Oracle使用RMAN备份数据库的流程步骤

    使用 RMAN(Recovery Manager)备份 Oracle 数据库是确保数据安全和可恢复性的关键步骤,下面是详细的指导和代码示例,展示如何使用 RMAN 进行数据库备份,感兴趣的小伙伴跟着小编一起来看看吧
    2024-09-09

最新评论