环境是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;

解决方案 »

  1.   

    问题补充如下,当采用另一种方式防止反复插入时,当输入正常新记录时弹出了-20002,Unknown Errors,还是无法正常插入。DECLARE
      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;
      

  2.   

    可以调整一下表格的字段.假设表格字段如:
      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字段要置空.
    这样的缺点是,会多一个字段出来.
    其它的依样处理.
      

  3.   

    这样你的程序也可以提高速度.不要老是count(*)