`

ORA-14551: 无法在查询中执行 DML 操作

 
阅读更多

最近在调试一个带DML操作的函数时,一直不成功,在PL/SQL中测试时没问题,通过 SQL语句调用函数时就不行了,刚开始一直没找到原因,后来无意间把 函数中捕获异常的代码注释掉,终于通过SQL调试时,弹出了一个“ORA-14551: 无法在查询中执行 DML 操作 .”错误,找到了问题原因,就好找解决办法了,在网上找到一篇文章,大谈什么自治事务和主事务,看了半天,还是云里雾里,找到关键点,就是添加一条语句“PRAGMA AUTONOMOUS_TRANSACTION;”,并在最后 COMMIT 提交DML操作,问题迎刃而解,至于这个什么自治事务和主事务,还是有时间,后面再慢慢消化了。

----以下是引用文章:

在函数中,往临时表插入数据报错:

ORA-14551: 无法在查询中执行 DML 操作

ORA-06512: 在 "NSTCSA.NS_ST_GETRAISEFUNDX", line 29

 

增加下面的字符串:

PRAGMA AUTONOMOUS_TRANSACTION;

 

 

数据库事务是一种单元操作,要么是全部操作都成功,要么全部失败。在Oracle中,一个事务是从执行第一个数据管理语言(DML)语句开始,直到执行一个COMMIT语句,提交保存这个事务,或者执行一个ROLLBACK语句,放弃此次操作结束。

 

事务的“要么全部完成,要么什么都没完成”的本性会使将错误信息记入数据库表中变得很困难,因为当事务失败重新运行时,用来编写日志条目的INSERT语句还未完成。

 

针对这种困境,Oracle提供了一种便捷的方法,即自治事务。自治事务从当前事务开始,在其自身的语境中执行。它们能独立地被提交或重新运行,而不影响 正在运行的事务。正因为这样,它们成了编写错误日志表格的理想形式。在事务中检测到错误时,您可以在错误日志表格中插入一行并提交它,然后在不丢失这次插 入的情况下回滚主事务。

 

因为自治事务是与主事务相分离的,所以它不能检测到被修改过的行的当前状态。这就好像在主事务提交之前,它们一直处于单独的会话里,对自治事务来说,它们是不可用的。然而,反过来情况就不同了:主事务能够检测到已经执行过的自治事务的结果。

 

要创建一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQL Server语句都是自治的。

 

触发无法包含COMMIT语句,除非有PRAGMA AUTONOMOUS_TRANSACTION标记。但是,只有触发中的语句才能被提交,主事务则不行。

exp:

Create table Msg (Msg varchar(50)) ;
自制事务:
create or replace procedure AutoNomouse_Insert is
    PRAGMA AUTONOMOUS_TRANSACTION;
     begin
             insert into Msg values('AutoNomouse Insert');
            commit;
    end;
非自治事务:
CREATE OR REPLACE Procedure NonAutoNomouse_Insert as
    begin
           insert into Msg Values('NonAutonomouse Insert');
           commit;
    end;

SQL> begin
  2 
  3            insert into Msg Values('This Main Info');
  4 
  5            NonAutoNomouse_Insert;
  6 
  7            rollback;
  8 
  9  end
 10  ;
 11  /
 
PL/SQL procedure successfully completed
 
SQL> select * from msg;
 
MSG
--------------------------------------------------
This Main Info
NonAutonomouse Insert
因为过程中有COMMIT;所以匿名块中得RULLBACK 是不起作用的; 由此得出:非自治事务中的COMMIT,ROLLBACK
是会影响整个事务的。
下面我们看一个另外一种情况:
SQL> delete msg;
 
2 rows deleted
 
SQL>
 
这里没有COMMIT;

SQL> begin
  2 
  3            insert into Msg Values('This Main Info');
  4 
  5            rollback;  --这里加了ROLLBACK;
  6 
  7            NonAutoNomouse_Insert;
  8 
  9            rollback;
 10 
 11  end
 12  ;
 13  /
 
PL/SQL procedure successfully completed
 
SQL> select * from msg;
 
MSG
--------------------------------------------------
This Main Info
NonAutonomouse Insert
NonAutonomouse Insert
 
竟然没有ROLLBACK (DELETE * FROM SSG ;) 为什么了?因为过程就是一个新的SESSION,所以前面的SESSION
被正常EXIT,同时被自动提交; 所以我们会看到三行数据。
SQL> commit;
 
Commit complete
 
SQL> select * from msg;
 
MSG
--------------------------------------------------
This Main Info
NonAutonomouse Insert
NonAutonomouse Insert
 
SQL> commit;
 
Commit complete
 
SQL> select * from msg;
 
MSG
--------------------------------------------------
This Main Info
NonAutonomouse Insert
NonAutonomouse Insert
因为这里一个新的SESSION 所以是没有意义的事务控制语句。
 
SQL> delete msg;
 
3 rows deleted
 
SQL> commit;
 
Commit complete
 
SQL> select * from msg;
 
MSG
--------------------------------------------------
可以看到这里是正常的提交;
 
下面看一下自制事务:
SQL> begin
  2 
  3            insert into Msg Values('This Main Info');
  4 
  5            AutoNomouse_Insert;
  6 
  7            rollback;
  8 
  9  end
 10 
 11  ;
 12  /
 
PL/SQL procedure successfully completed
 
SQL> select * from msg;
 
MSG
--------------------------------------------------
AutoNomouse Insert
 
我们看到是一行数据,显然第一条SQL INSERT 是被ROLLBACK,证明自制事务是一个独立于主程序的事务,
他不会对主事务的控制产生影响。另外在分布式环境中我们经常会遇到 ORA-02064 ERROR ,就是因为主事务
自己有事务控制语句,然而被调用的远程过程也有自己的事物控制语句,当然就会报错,我们将被调用的过程
声明为自制事务那就OK了。
 

今天在函数中使用insert语句时,报了ora-14551 无法在查询中执行dml操作错误。

错误的解决办法,有两种:

一、在函数外面套存储过程;

二、使用自治事务(AUTONOMOUS TRANSACTION)

在函数声明部分加入这句话

PRAGMA AUTONOMOUS_TRANSACTION;

我选择了后一种。

分享到:
评论

相关推荐

    oracle报错大全(珍藏版)

    执行DML操作时发生错误。这可能是因为数据完整性问题、权限不足或其他数据库级别的问题。 #### ORA-00056: "." Schema Not Specified 在DDL语句中未指定模式名称时触发。这可能是因为DDL语句格式错误或逻辑错误。 ...

    Oracle错误代码大全

    * ORA-00034: 无法在当前 PL/SQL 会话中 二、资源错误 * ORA-00050: 获取入队时操作系统出错 * ORA-00051: 等待资源超时 * ORA-00052: 超出最大入队资源数 * ORA-00053: 超出最大入队数 * ORA-00054: 资源正忙,...

    Oracle error code 大全

    ORA-00034:无法在当前 PL/SQL 会话中 进程管理错误 ORA-00018:超出最大会话数 ORA-00019:超出最大会话许可数 ORA-00020:超出最大进程数 ORA-00021:会话附属于其它某些进程;无法转换会话 ORA-00072:进程号...

    oracle报错的详细列表

    当尝试在操作系统中分配的对象超出限制时触发。 #### ORA-00065: FIXED_DATE的初始化失败 当 `FIXED_DATE` 初始化失败时触发。 #### ORA-00066: LOG_FILES为但需要成为才可兼容 当 `LOG_FILES` 参数的值不符合兼容...

    oracle错误代码大全

    19. ORA-00034: 无法在当前PL/SQL会话中执行某些操作,可能涉及会话状态或功能限制。 20. ORA-00035: LICENSE_MAX_USERS不能小于当前用户数,这涉及到数据库许可证和并发用户数。 21. ORA-00036: 超过递归SQL调用...

    oracle数据库-错误编码大全

    当数据库中的对象太大,无法在操作系统上分配足够的空间时,将出现此错误。这通常要求增加操作系统的存储容量。 - ORA-00065: FIXED_DATE的初始化失败。在数据库实例启动过程中,由于环境变量FIXED_DATE设置错误,...

    Oracle错误代码大全.pdf

    19. ORA-00034: 无法在当前PL/SQL会话中执行某些操作,可能是由于会话限制或语法错误。 20. ORA-00035: LICENSE_MAX_USERS不能小于当前用户数,这涉及到数据库许可证限制。 21. ORA-00036: 超过递归SQL级别的最大...

    Oracle错误代码

    执行DML(数据操纵语言)操作时,锁的数量超过了系统允许的最大值。 #### ORA-00056: 对象'.'上的DDL锁以不兼容模式挂起 在执行DDL(数据定义语言)操作时,尝试获取的锁与现有锁模式不兼容。 #### ORA-00057: ...

    oracle错误代码详细的总结与分析.docx

    19. **ORA-00034: 无法在当前 PL/SQL 会话中:** 有些操作不能在PL/SQL会话中执行。 20. **ORA-00035: LICENSE_MAX_USERS 不能小于当前用户数:** 许可证限制的用户数量小于当前已登录的用户数。 21. **ORA-00036: ...

    Oracle错误代码集合[归类].pdf

    7. ORA-17007: 动态列的无效状态,这通常发生在动态SQL操作中,可能是由于执行过程中的语法或逻辑错误。 8. ORA-17008: 表示一个已经关闭的连接,意味着尝试在已关闭的连接上执行操作。 9. ORA-17009: 已关闭的...

    oracle错误一览表

    - **描述**: 在PL/SQL环境中执行某些操作时出现错误。 - **解决方法**: 检查PL/SQL代码中的错误,并确保所有必要的资源都可用。 **ORA-00035: LICENSE_MAX_USERS不能小于当前用户数** - **描述**: 尝试降低`LICENSE...

    ORACLE错误码及解决方法

    这些错误可能是因为试图在不存在的对象上操作,或者试图在非键保留的视图上执行DML语句。解决方案包括检查视图定义、主键或约束的存在性,以及视图依赖的其他对象。 错误码如ORA-00904、ORA-00906、ORA-00907等,...

    oracle常见错误及解决方法

    Oracle数据库在运行过程中可能会遇到各种错误,这些错误通常以ORA-XXXX的形式呈现,每个错误代码对应着特定的问题和解决策略。以下是一些常见的Oracle错误及其解释和解决方法: 1. ORA-00001: 违反唯一约束条件 当...

    Oracle所有错误

    表示在操作系统层面,对象尺寸超出了分配限制。检查操作系统设置或优化对象大小。 #### ORA-00065:FIXED_DATE的初始化失败 通常与日期相关的系统参数初始化失败有关。检查日期和时间设置。 #### ORA-00066:LOG_...

    oracle 错误一览表

    - **解决方法**:在执行操作前,确保指定了正确的用户。 #### ORA-00030: User ID not found - **描述**:找不到指定的用户ID。 - **解决方法**:确认用户ID拼写正确,并且该用户确实存在于数据库中。 #### ORA-...

Global site tag (gtag.js) - Google Analytics