环境是Oracle9i,有两个内容完全相同的表T,TCOPY,要求用触发器实现在其中任何一个表中进行的操作要反映到另一个表上,例如,其中一个表插入一条记录,另一个表也要插入同样一条记录。问题是,在两个表都设置了结构完全一样的插入触发器,其中一个表T插入记录,触发器会在另一个表TCOPY也插入记录,而这个插入行为又会引发TCOPY表的触发器在T表又插入同一条记录,如此循环形成触发链过长反复插入而出错。为解决这个问题,我在插入时检查插入的记录在表中是否存在,若不存在则插入,若存在则弹出意外。但是当插入记录时触发器还是引发了触发链过长的问题。请问这个触发器的设计哪里出了问题?其中一个的触发器主体如下,其触发条件是 before insert,逐行触发。DECLARE
Record_already_exist EXCEPTION;
cnt int;
begin
select count(*) into cnt
from oe.TCOPY
where (TID= :new.TID
and NAME= :new.NAME
and ADDRESS= :new.ADDRESS
and PHONE= :new.PHONE
);
if (cnt>=1)
then
raise Record_already_exist;
else
insert into T values(:new.TID,:new.NAME,:new.ADDRESS,:new.PHONE);
end if;
end;
Record_already_exist EXCEPTION;
cnt int;
begin
select count(*) into cnt
from oe.TCOPY
where (TID= :new.TID
and NAME= :new.NAME
and ADDRESS= :new.ADDRESS
and PHONE= :new.PHONE
);
if (cnt>=1)
then
raise Record_already_exist;
else
insert into T values(:new.TID,:new.NAME,:new.ADDRESS,:new.PHONE);
end if;
end;
Record_already_exist EXCEPTION;
cnt int;
begin
select count(*) into cnt from T where(tag=0); --表添加一个标识字段tag,默认为0,当tag为0时为新插入的记录,1则为以前的记录,以此来防止反复插入。
if (cnt!=0)
then
update T
set tag=1
where(tag=0);
raise Record_already_exist;
else
insert into TCOPY values(:new.TID,:new.NAME,:new.ADDRESS,:new.PHONE,:new.tag);
end if;
EXCEPTION
when Record_already_exist
then
RAISE_APPLICATION_ERROR(-20001,'Record already exist.');
when others
then
RAISE_APPLICATION_ERROR(-20002,'Unknown Errors.');
end;
t(Name varchar2(10),age int)
可以修改为
t(name varchar2(10),age int,src varchar2(10))以src记录发送的表格名字.
意思如下(假设只针对INSERT,其它的同此):
T:
if :new.src is null then
insert into tcopy(name,age,src) values(:new.name,:new.age,'T');
end if;Tcopy:
if :new.src is null then
insert into t(name,age,src) values(:new.name,:new.age,'Tcopy');
end if; 在应用方面,如果执行插入的时候,则应该分别是
insert into t(name,age,src) values(vname,vage,null);
insert into tcopy(name,age,src) values(vname,vage,null);
也就是说src字段要置空.
这样的缺点是,会多一个字段出来.
其它的依样处理.