问题描述
首先说明我要实现的功能:假设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)之后提交数据,在语句级触发器就可以使用提交后的数据
解决方案
好像这样就能实现了吧,不用中间表吧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;