现有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 FOOFOR 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 的值了
------解决方案--------------------