冰城野草-ICE
2013-06-17 10:47
浏览 241
已采纳

关于oracle触发器操作的疑问

 首先说明我要实现的功能:假设A表和B表,我想实现,在增加A表的同时,利用刚刚插入的数据和A表中已有的数据(包括刚刚插入的数据)进行如数据编码(code)组合,生成一个新的字符串插入到B表中的编码列;

我使用的Oracle客户端是PL/SQL devloper 8,

我现在想到的方案:

方案1:使用行触发器,在插入的时候使用new获取刚刚插入的数据,这样跟之前已经有的数据组合,但是这样当插入两条或多条的时候,会出现下一条总是无法和刚刚插入的数据组合,也就是不能发现同一批插入的数据;(按道理,两个SQL语句应该是两个事务,应该能使用刚刚插入的数据,这是第一个疑问,是不是客户端造成的,我的客户端设置是自动提交SQL,不应该有问题)

方案2:在第一种方案不能满足需求,我寻求了第二种方案,就是建立一个全局临时表,然后使用行触发器把新插入的数据放到临时表中,再最后做一次语句触发器,在语句级触发器中使用游标遍历临时表记录,跟已经存在的数据进行组合,插入到B表中;(疑问2:在插入多条数据的时候,比如两个insert语句,行触发器在临时表新增一条数据,然后触发了一次语句级触发器,然后行触发器在临时表又新增一条数据,然后又触发了一次语句级触发器,跟我预想的应该是两次行触发器,一次最终语句级触发不一样,不知道是不是我理解的不对;按照我的理解,两个insert语句应该是两个事务,这样临时表只会保留一条记录,但是目前确实是多条;如果两条insert在一个事务内,为什么又多次触发语句级触发器?);目前解决方法就是在语句触发器最后增加一条删除临时表数据,这样保证临时表始终是最新插入的数据。代码如下:

 

   CREATE   TABLE A
  (
       id     number,
        name     varchar2(30),
    birthdate    date
      ) ;
-- B表    
CREATE   TABLE B
  (
       id     number,
        name     varchar2(30),
    birthdate    date
      ) ;
-- 创建临时表 a_tt,存储刚刚插入的数据
    CREATE global temporary TABLE a_tt
  (id     number,
          name     varchar2(30),
    birthdate    date
      ) ON COMMIT DELETE ROWS;
 --A表的行触发器记录新插入的数据
create or replace trigger a_insert_row
      AFTER insert   on  A  for each row
         declare
 begin 
               insert into  a_tt(id,name,birthdate) values(:new.id,:new.name,:new.birthdate);
   end;   
   create or replace trigger aaaa_insert_tt  AFTER insert   on  A
              declare  
        v_name  aaaa_log.name%type;  
        cursor n_cur is select name  from a_tt;
            begin          
           dbms_output.put_line('语句触发器执行');
                for cur in  n_cur loop  
            dbms_output.put_line( cur.name);                                                        
        insert into B(name)  select cur.name ||'_' ||name  from A;  
        end loop;
                    --   delete from a_tt; --删除临时表过时数据          
        end;

 测试语句:

 insert  into A  values(2,'a',sysdate);         

insert  into A values(3,'b',sysdate);

 

预期结果:B表中name 列 2_2,3_2,3_3

 

希望各位大神,帮我理理思路,不知道我说清没有

触发器执行的时候是不是在行触发器(after)之后提交数据,在语句级触发器就可以使用提交后的数据

 

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • sanyo0714 2013-06-17 14:05
    已采纳

    好像这样就能实现了吧,不用中间表吧
    [code="sql"]
    create or replace trigger a_for_test
    before insert on a
    for each row declare

    cursor cur is
    select id as nm from a t;
    begin

    FOR i in cur LOOP
    insert into b
    (name, birthdate)
    values
    (i.nm || '_' || :new.id, sysdate);
    END LOOP;

    insert into b
    (name, birthdate)
    values
    (:new.id || '_' || :new.id, sysdate);
    end a_for_test;

    [/code]

    打赏 评论

相关推荐 更多相似问题