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;
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论