`
徜徉の小溪
  • 浏览: 448034 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

oracle出现ORA-04091错误时使用自治事务治标不治本

 
阅读更多
经常会有人提出这样的问题:“有一个这样的问题,有一个表A有 a,b,c,d四个字段,修改一条记录d的值为2的倍数,希望把该记录插入相同结构的表B中。并删除A表的这条记录。”
相关SQL:
--一张表
  1. create table FOO  
  2. (  
  3.   A NUMBER(10),  
  4.   B NUMBER(10),  
  5.   C NUMBER(10),  
  6.   D NUMBER(10)  
  7. )  
  8. ;  


--基于这张表的触发器
  1. CREATE OR REPLACE TRIGGER tri_foo  
  2. AFTER INSERT OR UPDATE ON foo  
  3. FOR EACH ROW  
  4. DECLARE  
  5.   N_NUM NUMBER(5);  
  6. BEGIN  
  7.   IF MOD(TRUNC(:NEW.D),2) =0 THEN  
  8.       DELETE FROM FOO WHERE FOO.D = :NEW.D;  
  9.   END IF;  
  10. END;  


  这个函数在执行的时候会报告这样的错误:“ORA-04091:表SCOTT.FOO 发生了变化,触发器/函数不能读它”。网上有很多关于该错误的解决方案,其中,有很大一部分是增加PRAGMA AUTONOMOUS_TRANSACTION语句,设置该触发器为自治事务,然后避免该错误。增加之后确实不报错了,而且貌似可以执行了,但是事真的如此么?修改之后的触发器如下:
  1. CREATE OR REPLACE TRIGGER tri_foo  
  2. AFTER INSERT OR UPDATE ON foo  
  3. FOR EACH ROW  
  4. DECLARE  
  5.  PRAGMA AUTONOMOUS_TRANSACTION;  
  6.   N_NUM NUMBER(5);  
  7. BEGIN  
  8.   IF MOD(TRUNC(:NEW.D),2) =0 THEN  
  9.       DELETE FROM FOO WHERE FOO.D = :NEW.D;  
  10.   END IF;  
  11.   COMMIT;  
  12. 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)尝试从业务端来解决这个需求。
分享到:
评论

相关推荐

    ERwin连接oracle报ORA-01041内部错误,hostdef扩展名不存在.docx

    在使用ERwin数据建模工具连接Oracle数据库时,可能会遇到ORA-01041内部错误提示:“hostdef扩展名不存在”。这一错误通常出现在尝试建立与Oracle服务器的连接过程中,导致ERwin无法正常工作。 #### 二、ORA-01041...

    ORACLE出现ORA-15414错误

    根据提供的描述,“登陆oracle时出现ora-15414时按照文档操作即可安全无压力”,我们可以推测此错误与配置文件`listener.ora`有关,并且可以通过调整该文件来解决。 #### ORA-15414错误含义 ORA-15414是Oracle...

    Oracle数据库发生ORA-04031错误原因浅析及处理.pdf

    但是在实际应用过程中经常会出现“ORACLE 的 JOB 无法执行”、“ORA-04031”等错误情况,给维护及使用带来问题。 ORA-04031错误信息产生的原因主要有两种情况: 1. Oracle进程在向SGA申请内存时,如果申请失败,将...

    Oracle_ORA-12518故障_处理

    ORA-12518/TNS-12518错误通常是由于监听器在将客户端连接移交给服务器进程或调度进程时出现问题所导致的。通过对监听器日志的分析、配置文件的检查、系统资源的调整等步骤,可以有效地解决这一问题。同时,针对不同...

    ORACLE ORA-00132 ORA-00214

    在Oracle数据库管理过程中,遇到ORA-00132和ORA-00214这类错误时,往往意味着数据库配置或启动过程中出现了问题。下面将对这两个错误进行详细解析,并给出相应的解决方案。 #### 二、ORA-00132: Syntax Error or ...

    Oracle 11gr2连Oracle 19c 报ORA-28040 ORA-01017解决方法.pdf

    Oracle数据库不同版本间的客户端与服务端的连接问题通常涉及到安全和兼容性配置,这篇文章主要讲述了在Oracle 11g R2客户端尝试连接Oracle 19c服务端时,遇到了两个特定的错误:ORA-28040和ORA-01017,以及如何解决...

    使用工具IMPDP导入数据时ORA-39002、ORA-39070错误排查

    在使用Oracle Data Pump工具IMPDP(Import Data Pump)进行数据导入的过程中,可能会遇到ORA-39002和ORA-39070等错误。本文将针对这些错误的排查方法进行详细介绍,帮助用户理解问题的原因及解决策略。 ### 错误...

    Oracle 10g启动后报ORA-16038错误的解决方法

    在启动Oracle 10g数据库时遇到ORA-16038错误,该错误通常与归档日志操作有关。具体错误信息为: ``` ORA-16038: log 1 sequence #230 cannot be archived ORA-19809: limit exceeded for recovery files ORA-00312: ...

    oracle ora-03113错误

    ORA-03113 是一个较为常见的Oracle错误,通常出现在网络通信出现问题时,具体表现为“end-of-file on communication channel”(通信通道上的文件结束)。此错误可能由多种因素引发,包括但不限于Unix核心参数设置...

    kettle连接oracle12C--报错ORA-28040 没有匹配的验证协议.rar

    当尝试使用Kettle连接Oracle 12c时,可能会遇到错误"ORA-28040:没有匹配的验证协议"。这个错误通常意味着客户端和服务器之间的安全认证不兼容。 **ORA-28040错误的解释:** 此错误通常出现在Oracle数据库服务器...

    Oracle12cRAC数据库 出现ora-12520, ora-12516

    在使用Oracle12cRAC(Real Application Clusters)数据库的过程中,可能会遇到客户端连接时出现ora-12520或ora-12516错误的问题。这两种错误代码分别表示“无法为服务找到可用实例”和“TNS:没有监听器”,通常与...

    远程连接Oracle报ORA-12545错误解决方案

    NULL 博文链接:https://ajita.iteye.com/blog/1725304

    oracle重启报错ORA-00702解决办法

    执行`startup`命令,如果出现ORA-00702错误,记录错误信息。 3. **修复数据文件**:确认出错的数据文件或控制文件是否损坏。在SQL*Plus中运行`SELECT file_name FROM v$datafile;`和`SELECT file_name FROM v$...

    oracle远程连接服务器出现 ORA-12170 TNS:连接超时 解决办法

    错误描述:oracle远程连接服务器出现 ORA-12170 TNS:连接超时 错误检查:有很多是oracle自身安装的问题,但是我这里服务器配置正常,监听正常,服务正常,远程可以ping通服务器。 这里主要是防火墙问题,解决办法: ...

    ora-00604错误解决方法

    ora-00604 错误 解决 方法 ora-00604 错误 解决 方法 ora-00604 错误 解决 方法 ora-00604 错误 解决 方法 ora-00604 错误 解决 方法ora-00604 错误 解决 方法

    oracle数据库ORA-29275.txt

    在Oracle数据库操作过程中,遇到ORA-29275错误时,通常意味着系统内部发生了某些问题,影响了数据库的正常运行。根据提供的部分脚本内容及上下文推测,ORA-29275错误可能与数据库字符集设置、会话限制或资源管理配置...

    Oracle SQL Developer连接报错(ORA-12505)的解决方案(两种)

    用oracle数据库新建连接时遇到ora-12505,此问题解决后又出现ora-12519错误,郁闷的半天,经过一番折腾问题解决,下面小编把我的两种解决方案分享给大家,仅供参考。  解决方案一: 今天工作时在新建连接的时候遇到...

    如何处理错误ORA-29275:部分多字节字符

    ### 如何处理错误ORA-29275:部分多字节字符 #### 问题背景与描述 在Oracle数据库操作过程中,用户可能会遇到一个特定的错误提示——ORA-29275:部分多字节字符。这一错误通常出现在执行查询`SELECT * FROM V$...

    关于创建oracle 连接时报以下错误,ORA-01017 ORA-02063

    在创建Oracle数据库连接时遇到的错误ORA-01017和ORA-02063涉及到用户认证问题以及Oracle数据库版本之间的差异处理。ORA-01017错误表示用户名或密码无效,登录被拒绝,而ORA-02063则通常表示在Oracle数据库之间进行...

Global site tag (gtag.js) - Google Analytics