1、初始目标
在对表h1插入一条数据时,同时插入一条重复的数据(只有主键不同)
2、在PL/SQL里New一个Trigger或者手动敲入代码
先说明一下,表h1包括4列ID、C1、C2、C3
create or replace trigger Trigger_Test
after insert on h1
for each row
declare
--variables
begin
insert into h1 values(:new.C1, :new.C2, :new.C3, :new.ID);
end Trigger_Test;
3、F8编译通过,新建一个窗口执行insert窗口,测试trigger是否有效,用了一个名为sequence_test的序列:
insert into h1 values('aa','bb','cc',sequence_test.nextval);
报错:表h1发生了变化,触发器/函数不能读。
4、网上搜的说法是“触发器不能修改触发表的数据,除非使用自治事务”,OK那就用自治事务:
declare
--variables
//改为:
declare
pragma autonomous_transaction;
再试报错:等待资源时检测到死锁。仔细一查,哦原来是目标有问题,Insert连着Insert,无限循环,不是资源死锁就是内存不足或者栈溢出。
5、目标更新为:在对表h1插入一条数据时,同时插入一条相同的数据到历史表里,把trigger里的insert修改为:
insert into h1_history values(:new.C1, :new.C2, :new.C3, :new.ID);
再跑又报错:检测到活动的自治事务处理,已经回退。
6、网上接着搜,说是有事务没提交。其实这是之前目标设定有问题,触发器一般不会修改触发表,用了自治事务,就要commit;如果是插入历史表,可以都不加。
declare
pragma autonomous_transaction;
commit;
delete from h1 where ID = 1;
commit;
//如果不操作触发表,则可以去掉自治事务的这一串声明
declare
insert into h1_history values(:new.C1, :new.C2, :new.C3, :new.ID);
7、小结
- Trigger在修改其他表(非触发表)的时候,最方便,直接像写存储过程即可;
- 若要使用Trigger修改触发表的数据,需要配合使用自治事务并commit,比较麻烦;
- 对新操作的记录本身(比如新Insert/Update/Delete的数据),无法做修改,并且如果强行修改的话,既不会报错,也没有效果。