关于自治事务解决触发器导致"ORA-04091:触发器/函数不能读它"不可行的验证
来源:互联网 发布:mac bash 改为 user 编辑:程序博客网 时间:2024/06/05 20:15
经常会有人提出这样的问题:“有一个这样的问题,有一个表A有 a,b,c,d四个字段,修改一条记录d的值为2的倍数,希望把该记录插入相同结构的表B中。并删除A表的这条记录。”
相关SQL:
--一张表
create table FOO( A NUMBER(10), B NUMBER(10), C NUMBER(10), D NUMBER(10));
--基于这张表的触发器
CREATE OR REPLACE TRIGGER tri_fooAFTER INSERT OR UPDATE ON fooFOR EACH ROWDECLARE N_NUM NUMBER(5);BEGIN IF MOD(TRUNC(:NEW.D),2) =0 THEN DELETE FROM FOO WHERE FOO.D = :NEW.D; END IF;END;
这个函数在执行的时候会报告这样的错误:“ORA-04091:表SCOTT.FOO 发生了变化,触发器/函数不能读它”。网上有很多关于该错误的解决方案,其中,有很大一部分是增加PRAGMA AUTONOMOUS_TRANSACTION语句,设置该触发器为自治事务,然后避免该错误。增加之后确实不报错了,而且貌似可以执行了,但是事真的如此么?修改之后的触发器如下:
CREATE OR REPLACE TRIGGER tri_fooAFTER INSERT OR UPDATE ON fooFOR EACH ROWDECLARE PRAGMA AUTONOMOUS_TRANSACTION; N_NUM NUMBER(5);BEGIN IF MOD(TRUNC(:NEW.D),2) =0 THEN DELETE FROM FOO WHERE FOO.D = :NEW.D; END IF; COMMIT;END;
让我们通过真实的数据来验证这个解决方案的不可行:
ChenZw> insert into foo values(1,1,1,2);
已创建 1 行。
ChenZw> select * from foo;
A B C D
---------- ---------- ---------- ----------
1 1 1 2
已选择 1 行。
--看,(1,1,1,2) 这条数据居然是可以插入的!
ChenZw> insert into foo values(2,2,2,2);
已创建 1 行。
ChenZw> select * from foo;
A B C D
---------- ---------- ---------- ----------
1 1 1 2
2 2 2 2
已选择2行。
-- 吆吆,我又插入了一条(2,2,2,2),是不是触发器失效了呀?
ChenZw> commit;
提交完成。
ChenZw> insert into foo values(3,3,3,2);
已创建 1 行。
-- 再插入一条数据
ChenZw> commit;
提交完成。
ChenZw> select * from foo;
A B C D
---------- ---------- ---------- ----------
3 3 3 2
已选择 1 行。
--这里,为什么? 为什么把我之前的数据都给我删掉了,而不是刚刚插入的那条?
总结一下,这里插入的执行顺序应该是这样的:
1)INSERT开启一个新的事务,写入一条(3,3,3,2)数据,但是该操作尚未提交。
2)触发器语句块执行,开启一个自治事务,删除表中的数据,但是WHERE FOO.D = :NEW.D能够圈到的包含(1,1,1,2),(2,2,2,2)两条数据,由于(3,3,3,2)与触发器不在一个事务中,并且未提交,所以触发器语句块看不到当前的数据。
3)触发器删除语句执行完成,然后提交。
4)INSERT语句的事务完成,提交。
作者 陈字文(热衷于PM\ORACLE\JAVA等,欢迎同行交流):ziwen#163.com 扣扣:4零9零2零1零零
所以有两点建议:
1)对于INSERT一条语句到数据库中,不要希望能通过触发器来删除该语句。
2)尝试从业务端来解决这个需求。
- 关于自治事务解决触发器导致"ORA-04091:触发器/函数不能读它"不可行的验证
- 通过在触发器中建立自治事务解决ORA-04091(不能读取被触发的表)
- [学习笔记]ORA-04091 触发器/函数不能读它 的解决
- oracle--ORA:04091:触发器/函数不能读它
- oracle 触发器update 出现ORA-04091: 表 **发生了变化, 触发器/函数不能读它
- 行级触发器对当前表操作,”ORA-04091: 表 XX 发生了变化, 触发器/函数不能读它“,解决方法
- ORA-04091:表XX发生了变化,触发器/函数不能读它
- ora 04091:表XX发生了变化,触发器/函数不能读它(lin49940)
- ORA-04091:表XX发生了变化,触发器/函数不能读它
- 自治事务触发器问题解答
- 触发器(自治事务)
- 关于触发器中表*发生了变化, 触发器/函数不能读它
- 解决触发器检测到活动的独立的事务处理, 已经回退、表发生了变化, 触发器/函数不能读它
- 关于oracle中触发器触发时,报“表发生了变化,触发器或函数不能读它”错误
- 利用自治事务技术写一个用于审计的触发器
- 表xxx发生了变化,触发器/函数不能读它
- 触发器/函数不能读
- 执行触发器失败 :-6519:ORA-06519: 检测到活动的自治事务处理, 已经回退
- 九度OJ 题目1127:简单密码
- 用C多线程实现当年微软的竞赛题
- pl/sql代码块
- ms sql server 存储过程(1)SET NOCOUNT { ON | OFF }实用讲解
- 电路可靠性设计与元器件选型
- 关于自治事务解决触发器导致"ORA-04091:触发器/函数不能读它"不可行的验证
- 由《30天自制操作系统》引发的漫画创作
- MyEclipse实现自动、定时、自定义发微博
- QT实现多窗口切换
- 运行PhotonControl 会出现几秒钟后自动停止
- How Google uses Linux(谷歌是怎么使用Linux的)
- 自动取微博所有粉丝姓名和电话
- The Django Book【第3章 动态Web页面基础 】
- Workspace in use or cannot be created, choose a different one.--错误解决办法