日期:2014-05-16  浏览次数:20795 次

求大牛们来帮帮忙!测试after触发器的时候出错oracle触发器行级的问题!!!万分感谢
本帖最后由 qq123renmin 于 2012-05-20 16:02:36 编辑 首先有3个表 emp1(和emp一样),emp2(和emp一样),std
std表中的信息,是部门号与该部门的平均工资
创建行级触发器,当在emp1插入信息时,把工资低于所属部门的平均工资的职员信息插入到emp2表中,并且需要将std表中的平均工资每次都更新。

create table std(deptno number(2),sal number(5));
insert into std values(10,2917);
insert into std values(20,2175);
insert into std values(30,1567);

create table emp1 
as select * from emp;

create table emp2 
as select * from emp;

我写的触发器如下:
create or replace trigger test
after insert on emp1
for each row 
declare
v_sal emp1.sal%type;
begin
select sal into v_sal from std where deptno=:new.deptno;
if
:new.sal<v_sal
then
insert  into  emp2 values(:new.EMPNO,:new.ENAME,:new.JOB,:new.MGR,:new.HIREDATE,:new.SAL,:new.COMM,:new.DEPTNO);
end if;
update std set sal=(select avg(sal) from emp1 group by deptno having deptno=:new.deptno) where deptno=:new.deptno;
end;

测试触发器如下:
insert into emp1 values(1222,'PING','CLERK',2222,to_date('9-27-2006','MM-DD-YYYY'),1900,NULL,20)


但是出错了!错误提示如下:
            *
第 1 行出现错误:
ORA-04091: 表 SCOTT.EMP1 发生了变化, 触发器/函数不能读它
ORA-06512: 在 "SCOTT.TEST", line 10
ORA-04088: 触发器 'SCOTT.TEST' 执行过程中出错

我把after改成before就可以成功 不过更新std表的时候慢一步,因为是before触发器嘛,但为什么after就不行呢!
求各位大牛给解释并帮忙解决下
万分感谢!!!!!!!!!
------解决方案--------------------
使用before就可以了吗?
我感觉存在着突变表的问题。
------解决方案--------------------
如果是after ,表示你的触发器是在insert 完 emp1时起作用,此时 emp1应该插入了数据,但未提交,也就是存在了脏数据。而此时触发器里又用到了emp1的查询,emp1数据发生了变化,造成emp1数据不一致。

如果是before,触发器起作用的时间是在Inert emp1前,此时emp1的数据是一致的,不会报错。

个人理解,仅供参考~
------解决方案--------------------
那我想用after做怎么能做对呢!?或者用before也可以,但是before要慢一步嘛 怎么做对呢?@2楼
------解决方案--------------------
引用:
如果是after ,表示你的触发器是在insert 完 emp1时起作用,此时 emp1应该插入了数据,但未提交,也就是存在了脏数据。而此时触发器里又用到了emp1的查询,emp1数据发生了变化,造成emp1数据不一致。

如果是before,触发器起作用的时间是在Inert emp1前,此时emp1的数据是一致的,不会报错。

个人理解,仅供参考~
那我想用after做怎么能做对呢!?或者用before也可以,但是before要慢一步嘛 怎么做对呢?