最近工作中写了一触发器报错:ORA-04091:table XX  is mutating, trigger/function may not see it。

下面通过官方文档及网友提供资料分析一下错误原因及解决方法:

1.查看oracle官方文档:

原因:触发器(或者被语句中引用的用户自定义PL/SQL函数)视图去查询(或修改)一个被另一语句修改而触发的表。

解决方法:重写触发器(或函数)避免读该表。

2.根据错误原因我们写如下触发器,重现错误:

使用scott方案,创建一下表、触发器:

  1. SQL> create table tr_table as select * from emp;
  2. 表已创建。
  3. SQL> edit
  4. 已写入 file afiedt.buf
  5. 1  create or replace trigger tr_test
  6. 2  after update on emp
  7. 3  for each row
  8. 4  begin
  9. 5     update tr_table t set t.sal = (select sal from emp where empno=t.empno and empno=:new.empno);
  10. 6* end;
  11. SQL> /
  12. 触发器已创建
  13. SQL> update emp set sal=3700 where empno=7788;
  14. update emp set sal=3700 where empno=7788
  15. *
  16. 第 1 行出现错误:
  17. <span style="color:#ff0000;">ORA-04091: 表 SCOTT.EMP 发生了变化, 触发器/函数不能读它
  18. </span>ORA-06512: 在 "SCOTT.TR_TEST", line 2
  19. ORA-04088: 触发器 'SCOTT.TR_TEST' 执行过程中出错

3.原因分析:

在Oracle中执行DML语句的时候是需要显示进行提交操作的。当我们进行插入的时候,会触发触发器执行对触发器作用表和扩展表的种种操作,但是这个时候触发器和插入语句是在同一个事务管理中的,因此在插入语句没有被提交的情况下,我们无法对触发器作用表进行其他额外的操作。如果执行其他额外的操作则会抛出如上异常信息。

4.解决方案:

1) 我们知道,出错的原因是因为触发器和DML语句在同一事务管理中,所以方案一便是将触发器和DML语句分成两个单独的事务处理。这里可以使用Pragma autonomous_transaction; 告诉Oracle触发器是自定义事务处理。

SQL语句如下:

  1. create or replace trigger tr_test
  2. after update on emp
  3. for each row
  4. declare
  5. pragma autonomous_transaction;
  6. begin
  7. update tr_table t set t.sal = (select sal from emp where empno=t.empno and empno=:new.empno);
  8. commit; --此处需要显示提交
  9. end;

注:以上语句并不能实时获得更新的值。。。原因是我们在update emp表后还没来得及提交sal就触发了触发器,这个时候获取到的只能是老的sal值。

2) 在Oracle Trigger中有:new,:old两个特殊变量,当触发器为行级触发器的时候,触发器就会提供new和old两个保存临时行数据的特殊变量,我们可以从俩个特殊的变量中取出数据执行扩张表的DML操作。

SQL语句如下:

  1. create or replace trigger tr_test
  2. after update on emp
  3. for each row
  4. begin
  5. update tr_table t set t.sal = :new.sal;
  6. end;
  7. /

5. 再次插入数据:

  1. SQL> update emp set sal=3800 where empno=7788;
  2. 已更新 1 行。
  3. SQL> commit;
  4. 提交完成。
  1. SQL> select * from tr_table;
  2. EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
  3. ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
  4. 7369 SMITH      CLERK           7902 17-12月-80            800                    20
  5. 7499 ALLEN      SALESMAN        7698 20-2月 -81           1800        300         30
  6. 7521 WARD       SALESMAN        7698 22-2月 -81           1250        500         30
  7. 7566 JONES      MANAGER         7839 02-4月 -81           2975                    20
  8. 7654 MARTIN     SALESMAN        7698 28-9月 -81           1250       1400         30
  9. 7698 BLAKE      MANAGER         7839 01-5月 -81           2850                    30
  10. 7782 CLARK      MANAGER         7839 09-6月 -81           2450                    10
  11. <span style="BACKGROUND-COLOR: #009900">7788 SCOTT      ANALYST         7566 19-4月 -87           3800                    20
  12. </span>      7839 KING       PRESIDENT            17-11月-81           5000                    10
  13. 7844 TURNER     SALESMAN        7698 08-9月 -81           1500          0         30
  14. 7876 ADAMS      CLERK           7788 23-5月 -87           1100                    20
  15. EMPNO ENAME      JOB              MGR HIREDATE              SAL       COMM     DEPTNO
  16. ---------- ---------- --------- ---------- -------------- ---------- ---------- ----------
  17. 7900 JAMES      CLERK           7698 03-12月-81            950                    30
  18. 7902 FORD       ANALYST         7566 03-12月-81           3000                    20
  19. 7934 MILLER     CLERK           7782 23-1月 -82           1300                    10
  20. 已选择14行。

ORA-04091错误原因与解决方法的更多相关文章

  1. coreseek常见错误原因及解决方法

    coreseek常见错误原因及解决方法 Coreseek 中文全文检索引擎 Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和 ...

  2. /usr/bin/ld: cannot find -lc错误原因及解决方法

    问题解决 我在执行如下命令的时候,出现了错误. gcc -o main main.c -static -L. –lmylib Linux环境下gcc静态编译/usr/bin/ld: cannot fi ...

  3. SpringBoot+Shiro引起事务失效、错误原因、解决方法

    一.问题今天发现用户注册的Service的事务并没有起到作用,再抛出一个RuntimeException后,并没有发生回滚,下面是调试步骤: 1.检查数据库的引擎是否是innoDB 2.启动类上是否加 ...

  4. httpclient org.apache.http.NoHttpResponseException: host:端口 failed to respond 错误原因和解决方法

    原因:httpclient 之前与服务端建立的链接已经失效(例如:tomcat 默认的keep-alive timeout :20s),再次从连接池拿该失效链接进行请求时,就会保存. 解决方法:官方链 ...

  5. SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape错误原因及解决方法

    用Python打开文件: with open('C:\Users\PINPIN\test\file1.txt','r') as f2: pass 运行后直接就报错了: File "<i ...

  6. iBatis查询时报"列名无效"或"找不到栏位名称"无列名的错误原因及解决方法

    iBatis会自动缓存每条查询语句的列名映射,对于动态查询字段或分页查询等queryForPage, queryForList,就可能产生"列名无效".rs.getObject(o ...

  7. c++ std::sort函数调用经常出现的invalidate operator<错误原因以及解决方法

    在c++编程中使用sort函数,自定义一个数据结构并进行排序时新手经常会碰到这种错误. 这是为什么呢?原因在于什么?如何解决? 看下面一个例子: int main(int, char*[]) { st ...

  8. 移动端页头推荐配置 出现找不到favicon.ico错误原因和解决方法

    favicon 在未指定 favicon 时,大多数浏览器会请求 Web Server 根目录下的 favicon.ico .为了保证 favicon 可访问,避免404,必须遵循以下两种方法之一: ...

  9. javascript中出现identifier starts immediately after numeric literal错误原因以及解决方法

    javascript遇到参数是字符型和数字型组合的参数就会出现这种错误,例如alert(1);可以正確輸出alert(str);就會報錯alert("str");可以正確輸出.

随机推荐

  1. 条件语句,while循环语句:完整的温度转换程序

    while True: a = int(input('摄氏温度换为华氏温度请按 1\n华氏温度转为摄氏温度请按 2\n退出请按 3\n')) if a==1: c = float(input('请输入 ...

  2. 介绍Docker容器

    容器是 Docker 又一核心概念. 简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境.对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用 ...

  3. Docker与容器

    Docker介绍 1. Docker 主要解决什么问题 Docker 对外宣称的是Build.Ship 和Run,Docker 要解决的核心问题就是快速地干这三件事情.它通过将运行环境和应用程序打包到 ...

  4. Appium移动自动化框架初探

    作者:cryanimal QQ:164166060 本文简要介绍了appnium自动化框架的架构.加载流程.支持语言.相关配置,以及元素定位工具等. 官方网站: http://appium.io Ap ...

  5. C++:如何删除string对象的末尾非数字字符

    功能实现: 现有一个string对象包含数字字符以及非数字字符,实现删除string对象的末尾非数字字符. 实例: 输入为"0 1 1 2 3    " 输出为"0 1 ...

  6. Linux下C/C++程序调试基础(GCC,G++,GDB,CGDB,DDD)

    在写程序的时候,经常会遇到一些问题,比如某些变量计算结果不是我们预期的那样,这时我们需要对程序进行调试.本文主要介绍调试C/C++在Linux操作系统下主要的调试工具. 在Linux下写程序,C/C+ ...

  7. Swift中不用桥接文件和.h头文件直接和C代码交互的方法

    我们知道一般情况下Swit要想调用obj-c,c或c++代码必须通过obj-c以及桥接文件才可以办到,但是对于某些简单的代码,我们可以跳过桥接文件和.h头文件,直接和C代码交互呢! 我们再Projec ...

  8. Java学习之二维数组定义与内存分配详解

    二维数组:就是元素为一维数组的一个数组. 格式1: 数据类型[][] 数组名 = new 数据类型[m][n]; m:表示这个二维数组有多少个一维数组. n:表示每一个一维数组的元素有多少个. 注意: ...

  9. Struts 1 之<logic>标签库

    1. logic:empty logic:empty标签是用来判断是否为空的.如果为空,该标签体中嵌入的内容就会被处理.该标签用于以下情况: 当Java对象为null时 当String对象为" ...

  10. 带你深入理解STL之Deque容器

    在介绍STL的deque的容器之前,我们先来总结一下vector和list的优缺点.vector在内存中是分配一段连续的内存空间进行存储,其迭代器采用原生指针即可,因此其支持随机访问和存储,支持下标操 ...