求教Oracle数据库,表的行级触发器(涉及一连串的触发)。先网问题,紧急求助!!!急!!!
场景:一共3张表,用A,B,C表示。两个触发器,用W,Y表示。触发器都是行级触发 AFTER INSERT OR UPDATE FOR EACH ROW
在插入或更新A表数据后,使用A表触发器W在B表插入一条记录,在B表插入的数据中有一个字段为A表的关键字。
在插入或更新B表数据后,使用B表触发器Y在C表再插入一条数据,C表的大部分字段都是A表新插入记录的字段值。
(听起来似乎有点繁琐,但由于涉及3个厂家,A,B,C表分别在3个数据库上,是使用数据库链接来实现的)
问题:每次插入或更新C表的数据都落后了一步,即实际插入C表的数据都是A表OLD的值。
对问题自己的理解:自己调试,发现在C表的触发器Y中,使用查询语句select * from A where A.关键字=NEW.xxx。(xxx是B表的字段,其值为A表新插入的关键字)查询出来的记录还是更新前的数据。
似乎是在执行触发器Y中,A表的插入记录并没有提交。
我不知道我的这种理解对不对?另外使用触发器是否能实现我的这种需求啊?万分感谢大家提出宝贵意见!!!

解决方案 »

  1.   

    按你所说的模拟了一下,似乎是“异动表”的情况,这个语句 select * from A where A.关键字=NEW.xxx
    会有问题,列出所有字段应该可以。
    SQL> create table a(id number primary key,name varchar2(10));表已创建。SQL> create table b(id number primary key,name varchar2(10));表已创建。SQL> create table c(id number primary key,name varchar2(10));表已创建。SQL> create or replace trigger w
      2  after insert or update on a
      3  for each row
      4  declare
      5  begin
      6  if inserting then
      7     insert into b values(:new.id,:new.name);
      8  end if;
      9  end;
     10  /触发器已创建SQL> create or replace trigger y
      2  after insert or update on b
      3  for each row
      4  declare
      5  begin
      6  if inserting then
      7     insert into c select * from a where id=:new.id;
      8  end if;
      9  end;
     10  /触发器已创建SQL> insert into a values(1,'test');
    insert into a values(1,'test')
                *
    ERROR 位于第 1 行:
    ORA-04091: 表 CHENNAN.A 发生了变化,触发器/函数不能读
    ORA-06512: 在"CHENNAN.Y", line 4
    ORA-04088: 触发器 'CHENNAN.Y' 执行过程中出错
    ORA-06512: 在"CHENNAN.W", line 4
    ORA-04088: 触发器 'CHENNAN.W' 执行过程中出错
    SQL> create or replace trigger y
      2  after insert or update on b
      3  for each row
      4  declare
      5  begin
      6  if inserting then
      7     insert into c values(:new.id,:new.name);
      8  end if;
      9  end;
     10  /触发器已创建SQL> insert into a values(1,'test');已创建 1 行。SQL> select * from a;        ID NAME
    ---------- ----------
             1 test已选择 1 行。SQL> select * from b;        ID NAME
    ---------- ----------
             1 test已选择 1 行。SQL> select * from c;        ID NAME
    ---------- ----------
             1 test已选择 1 行。SQL>
      

  2.   

    select * from A where A.关键字=NEW.xxx
    这样用不行.表A属于变异状态..也就是常说的变异表
    改为1楼那样就哦了..
      

  3.   


    楼主的意思是更新后C表插入的是旧值?
    我写了个测试过,没问题:
    SQL> create table a(id number primary key,name varchar2(10));表已创建。SQL> create table b(id number primary key,name varchar2(10));表已创建。SQL> create table c(id number primary key,name varchar2(10));表已创建。SQL> create or replace trigger w
      2  after insert or update on a
      3  for each row
      4  declare
      5  begin
      6  if inserting then
      7     insert into b values(:new.id,:new.name);
      8   elsif updating then
      9      update b set name=:new.name where id=:old.id;
     10   end if;
     11  end;
     12  /触发器已创建SQL> create or replace trigger y
      2  after insert or update on b
      3  for each row
      4  declare
      5  begin
      6     insert into c values(:new.id+1,:new.name);
      7  end;
      8  /触发器已创建SQL> insert into a values(1,'test');已创建 1 行。SQL> select * from a;        ID NAME
    ---------- ----------
             1 test已选择 1 行。SQL> select * from b;        ID NAME
    ---------- ----------
             1 test已选择 1 行。SQL> select * from c;        ID NAME
    ---------- ----------
             1 test已选择 1 行。SQL> update a set name='update' where id=1;已创建 1 行。SQL> select * from a;        ID NAME
    ---------- ----------
             1 update已选择 1 行。SQL> select * from b;        ID NAME
    ---------- ----------
             1 update已选择 1 行。SQL> select * from c;        ID NAME
    ---------- ----------
             1 test
             2 update已选择 1 行。
      

  4.   

    哦,C表不用设置主键!B表触发语句那个ID不用加1!(失误)
    在C表中就可以看到那个第二条数据"update"就是A表中更新后的值!
      

  5.   

    呵呵,跟我同样的问题,看来用这种做法跟思路的人还不少http://topic.csdn.net/u/20080728/19/5fb11f9f-7c83-4682-85cf-0feb8dc610b4.html?seed=219900196
      

  6.   

    我也是采用数据库链接,不同的是我是在触发器中调存储过程去select数据,(因数据不能从:NEW中取)
    加上了自冶事务,select前加上commit也没用
    后来又想通过视图触发器来做,这样就可以用:NEW了 
    我的看法
    这个可能是触发器的事务原因,第一个触发器发起后,这时数据是脏数据,还没有提交,取不到最新的数据(脏数据)一串的触发器是同一个事务,只有最后一个触发器完成后才提交写入库,这是select才取到最近的数据。所以是没办法select取到第一个触发器更新的数据的第一个触发器发起是父事务,后面的是子事务,只有父事务提交了才行不知道是不是这样,没有查过文档,个人猜想