关于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)之后提交数据,在语句级触发器就可以使用提交后的数据

 

yue0706
冰城野草-ICE 额,首发,问题格式没有调整好
6 年多之前 回复

1个回答

好像这样就能实现了吧,不用中间表吧
[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]

yue0706
冰城野草-ICE 恩,功能能实现,目前我也是按照好几个方式实现(包括你提供的这种方式),只不过按照设定逻辑我希望在after触发器实现,然后这样同时提交多条插入语句的时候,事务级临时表的数据在多个插入语句的时候没有清空数据,而是继续添加;按照事务级别临时表定义,提交一个事务,临死表应该清空,不知道同时执行几个插入语句,是否为同一个事务,还是几个事务都处于未提交状态,直到最后一条才提交?现在我对于事务和触发器这块儿有点迷惑啊
6 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!