问题是这样的我建了个表stu(no number,name varchar2(15),adistance number,update_times integer);
表内容如下:
        NO NAME             ADISTANCE UPDATE_TIMES
---------- --------------- ---------- ------------
     10001 sfdf                   450            0
     10002 Raxxer                 475            0
     10003 CrystalMM              600            0
     10006 Magina                 450            0
     10004 SandKing               420            0
     10005 SkeletonKing           420            0
     10009 Flypig                 650            0
我就是想写个触发器实现,当我更新修改表中name的时候,对应的update_times会自动加1,例如当我
update stu set name='Terrorblade' where no=10001;后在触发器里实现对update_times自动加1;
我写的触发器是这样的如下:
create or replace trigger au_stu_trg
after update of name on stu
for each row
begin
update stu set adistance=+1 
where name=:old.name;
end;
/但我update后:
SQL> update stu set name='Terrorblade' where no=10001;
update stu set name='Terrorblade' where no=10001
       *
第 1 行出现错误:
ORA-04091: 表 SYSTEM.STU 发生了变化, 触发器/函数不能读它
ORA-06512: 在 "SYSTEM.AU_TR_GTT", line 2
ORA-04088: 触发器 'SYSTEM.AU_TR_GTT' 执行过程中出错
ORA-06512: 在 "SYSTEM.BU_TR_STU", line 2
ORA-04088: 触发器 'SYSTEM.BU_TR_STU' 执行过程中出错到网上看说是触发器不能对它本身的表操作,就是说如果你在表A上建了触发器,那么该触发器就不能针对表A再操作了,我也搞不懂到底是不是这样,还望哪位能给个明确答复!!抱着试试看的想法我又用了下面的方法:
临时表+2个触发器:
临时表gtt(no number)用来暂时存储stu表中name更新行的no,
临时表:create  global temporary table gtt(name varchar2(15)) on commit delete rows;
当更新stu表name时触发器bu_tr_stu实现向gtt中暂存更新行的no
create or replace trigger bu_tr_stu
before update of name on stu
for each row
begin
insert into gtt select no from stu where name=:new.name;
end;
/
下面又创建了触发器 au_tr_gtt,当gtt里有no插入的时候实现对stu表的update_times加1
create or replace trigger au_tr_gtt
after insert on gtt
for each row
begin
update stu set adistance=+1 where
no in (select no from gtt);
end;
/运行后还是报错,我要崩溃了,到底该怎么写啊!

解决方案 »

  1.   

    等的真着急,没闲着又到网上看了看,发现这么写就搞定了,
    最关键的就是触发器不能对本表做update,
    另外必须是before才能对new表修改,换成after就会报错,无法修改。
    最后是赋值的时候=前面要加冒号是必须的。

    记着这点下面的就好写了,既然不能用update来指定哪一行update_tims实现自动加,
    那就考虑最简单最基本的最原始的算法,只要是同一字段在old和new表里不一样的就表示它要被update了,
    就前后做个比较,if。。then语句简单搞定!
    create or replace trigger update_fre
    before update of name on stu
    for each row
    begin
    if :new.name<>:old.name then
     :new.update_times:=:old.update_times+1;
    end if;
    end;
    /问题是解决了,还希望各位看看还有没有其他比较巧的方法!
      

  2.   

    确实这个方式已经很简单了,前面的错误是你对trigger的不了解造成的你上面的trigger是行级的fow each row,在这样的trigger里是不能对自己的表做查询和DML语句。除非是自己管理事务。并不是trigger不能对自己的表操作,比如表级tirgger是可以的。所以你1楼的错,还是错在这里,你还是用的行级对于行级,修改row的值,只是在before的triiger里对new值做一下赋值操作就可以了。
      

  3.   

    4楼说的这样的trigger里是不能对自己的表做查询和DML语句。除非是自己管理事务,我试了下行级trigger是不能对自己表做任何修改包括查询操作,能解释下原因吗?还有你说“除非是自己管理事务”,我是刚学oracle专业术语不太理解,你能否给个例子详细说明下,万分感谢!