日期:2014-05-17  浏览次数:20875 次

触发器提示 触发器/函数不能读
现有foo表,表结构如下
字段 A B
  1 2010-4-22 11:30:16
  100 2010-3-22

我想实现的功能是在对表foo进行insert和update时,如果A的值是‘1’的话,B的值自动更新为当前日期

我写的触发器如下:
CREATE OR REPLACE TRIGGER AIUFER_FOO
  BEFORE INSERT OR UPDATE
  ON FOO
FOR EACH ROW 
DECLARE
  FOO_COUNT INT;
BEGIN
  SELECT COUNT(*) INTO FOO_COUNT FROM FOO 
  WHERE :NEW.A=1;
  IF FOO_COUNT>0 THEN
  :NEW.B:=SYSDATE;
  END IF;
END;

编译没有错误

我执行如下语句时
  INSERT INTO FOO VALUES(1,TO_DATE('20100305','YYYY-MM-DD'))
是正确的,b字段的值自动更新为当前日期

但是当我执行
  UPDATE FOO SET A=1
就会出现如下错误:
ORA-04091:表abc.foo发生了变化,触发器和函数不能读等错误


请问这时什么原因,是触发器写的不正确吗?如果要实现上述的功能应该怎么写呢??
先谢谢各位了啊!!

------解决方案--------------------
SQL code

CREATE OR REPLACE TRIGGER AIUFER_FOO
  BEFORE INSERT OR UPDATE
  ON FOO
FOR EACH ROW  
BEGIN
  IF :NEW.A = 1 THEN
    SELECT SYSDATE INTO :NEW.B FROM DUAL;
  END IF;
END;

------解决方案--------------------
变异表的问题,这种情况,需要用自治事务。


CREATE OR REPLACE TRIGGER AIUFER_FOO
BEFORE INSERT OR UPDATE
ON FOO
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
FOO_COUNT INT;
BEGIN
SELECT COUNT(*) INTO FOO_COUNT FROM FOO
WHERE :NEW.A=1;
IF FOO_COUNT>0 THEN
:NEW.B:=SYSDATE;
END IF;
END;
------解决方案--------------------
在触发器中一般不能查询基表,虽然自治事务可以,但容易造成死锁问题
所以尽不要使用这种方案,象这种问题,使用前端控制或者通
过存储过程控制!
触发器和自治事务不要滥用。
------解决方案--------------------
用after触发器
------解决方案--------------------
SELECT COUNT(*) INTO FOO_COUNT FROM FOO
WHERE :NEW.A=1;
IF FOO_COUNT>0 THEN
:NEW.B:=SYSDATE;
END IF;

改为 if NEW.A=1 then 
:NEW.B:=SYSDATE;
END IF;
------解决方案--------------------
至于改为after后 因为此时值已经提交了
所以你不能在修改 :NEW.B 的值了
------解决方案--------------------
探讨

那能不能解释一下,为什么在insert时候就不提示错误呢,而在update时确提示错误啊??
谢谢各位了啊,我在加分!