最近公司在做应用集成的权限集成部分,由于三家开发商联合开发,所以各厂商之间很多数据的交互,全量,增量。对于好久不写触发器的我,兼职晴天霹雳...在写的过程中,遇到了一些小问题,所以记录下来。
create or replace trigger alterUser before insert or update or delete on A for each row;
declare
userId varchar2(32);
countUsers number;
begin
userId := :new.user_id;
select count(1) into countUsers from A where user_id = userId;
if inserting or updating then
if countUsers <= 0 then
insert into B.......
else
update B .....
end if;
end if;
if deleting then
delete from B....
end if ;
end;
/
结果在操作的时候,报错,ora04091:表发生了变化,触发器不能读它....
先说一下解决方案,就是使用了自治事务,在declare下面,声明了一个自治事务,pragma autonomous_transaction,然后在各个DML操作之后都手动提交一下。
先了解一下自治事务,数据的主事务,导致了要么全成功,要么全失败的局面,继而导致了在失败的情况下需要做一些成功的事变得很难做到,比如记录日志。所以oracle为我们提供了自治事务,也可以叫子事务,是一种建立在主事务上的内部事务,主事务的提交回滚影响子事务的结果,然是子事务的提交回滚不影响主事务的结果。
然后又百度了一下,我遇到的这种问题, 也可以叫变异表问题,变异表的意思就是说,当对表进行DML操作的时候,所操作的表就变成了变异表,对表的行级触发器将不能再对表进行DML操作,我认为是对表DML操作需要提交,而在提交之前,如果行级触发器中也有对表的DML操作的话,如果行级触发的DML操作提交了(比如运用了上面说过的自治事务),但是对表的DML操作回滚了,那么将产生错误的结果,所以oracle不允许我们这么做。所以面对这种问题,暂时能想到的只有两种解决方案,一种就是运用自治事务,手动提交。第二种就是两个触发器,一个变异表的行级触发器无法对表进行DML操作的时候,不妨引发另一个表的触发器,让另一个可以进行DML的触发器进行DML操作。
create or replace trigger alterUser before insert or update or delete on A for each row;
declare
userId varchar2(32);
countUsers number;
pragma autonomous_transaction;
begin
userId := :new.user_id;
select count(1) into countUsers from A where user_id = userId;
if inserting or updating then
if countUsers <= 0 then
insert into B.......
commit;
else
update B .....
commit;
end if;
end if;
if deleting then
delete from B....
commit;
end if ;
end;
/