当前位置: 首页 > news >正文

mysql启动错误1455_PL/SQL“ ORA-14551: 无法在查询中执行 DML 操作”解决

环境

Oracle 11.2.0 + SQL Plus

问题

根据以下要求编写函数:将scott.emp表中工资低于平均工资的职工工资加上200,并返回修改了工资的总人数。PL/SQL中有更新的操作,执行此函数报如下错误:ORA-16551: 无法在查询中执行 DML 操作。

解决

在声明函数时加上: PRAGMA AUTONOMOUS_TRANSACTION; 并在执行完DML后COMMIT。

操作日志

--登录到Oracle

C:\Users\Wentasy>sqlplus wgb

SQL*Plus: Release 11.2.0.1.0 Production on 星期六 6月 29 15:32:21 2013

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

输入口令:

连接到:

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

--编写函数

SQL> CREATE OR REPLACE FUNCTION raise_sal

2  RETURN NUMBER

3  IS

4  v_num NUMBER:=0;

5  v_avg emp.sal%TYPE;

6  BEGIN

7    SELECT AVG(sal) INTO v_avg FROM emp;

8    UPDATE emp SET sal=sal+200 WHERE sal < v_avg;

9    v_num:=SQL%ROWCOUNT;

10    RETURN v_num;

11  END raise_sal;

12  /

函数已创建。

--调用函数,出现错误

SQL> SELECT raise_sal() FROM DUAL;

SELECT raise_sal() FROM DUAL

*

第 1 行出现错误:

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

ORA-06512: 在 "WGB.RAISE_SAL", line 8

--加上PRAGMA AUTONOMOUS_TRANSACTION和COMMIT。

SQL> CREATE OR REPLACE FUNCTION raise_sal

2  RETURN NUMBER

3  IS

4  PRAGMA AUTONOMOUS_TRANSACTION;

5  v_num NUMBER:=0;

6  v_avg emp.sal%TYPE;

7  BEGIN

8    SELECT AVG(sal) INTO v_avg FROM emp;

9    UPDATE emp SET sal=sal+200 WHERE sal < v_avg;

10    v_num:=SQL%ROWCOUNT;

11    COMMIT;

12    RETURN v_num;

13  END raise_sal;

14  /

函数已创建。

--验证第一步:查询薪水平均值

SQL> SELECT AVG(sal) FROM emp;

AVG(SAL)

----------

2543.75

--验证第二步:查询薪水比平均薪水低的员工的总数

SQL> SELECT count(sal) FROM emp WHERE sal < (SELECT AVG(sal) FROM emp);

COUNT(SAL)

----------

8

--验证第三步:查询数据

SQL> SELECT ename, sal FROM emp;

ENAME            SAL

---------- ----------

SMITH            1600

ALLEN            2400

WARD            2050

JONES            2975

MARTIN          2050

BLAKE            2850

CLARK            2450

KING            5000

TURNER          2300

JAMES            1750

FORD            3000

ENAME            SAL

---------- ----------

MILLER          2100

已选择12行。

--验证第四步:调用函数,如果为8,则实现功能

SQL> SELECT raise_sal() FROM dual;

RAISE_SAL()

-----------

8

--验证第五步:再次查询表数据

SQL> SELECT ename, sal FROM emp;

ENAME            SAL

---------- ----------

SMITH            1800

ALLEN            2600

WARD            2250

JONES            2975

MARTIN          2250

BLAKE            2850

CLARK            2650

KING            5000

TURNER          2500

JAMES            1950

FORD            3000

ENAME            SAL

---------- ----------

MILLER          2300

已选择12行。

参考资料

引用文字——更好的理解自治事务

数据库事务是一种单元操作,要么是全部操作都成功,要么全部失败。在Oracle中,一个事务是从执行第一个数据管理语言(DML)语句开始,直到执行一个COMMIT语句,提交保存这个事务,或者执行一个ROLLBACK语句,放弃此次操作结束。事务的“要么全部完成,要么什么都没完成”的本性会使将错误信息记入数据库表中变得很困难,因为当事务失败重新运行时,用来编写日志条目的INSERT语句还未完成。针对这种困境,Oracle提供了一种便捷的方法,即自治事务。自治事务从当前事务开始,在其自身的语境中执行。它们能独立地被提交或重新运行,而不影响正在运行的事务。正因为这样,它们成了编写错误日志表格的理想形式。在事务中检测到错误时,您可以在错误日志表格中插入一行并提交它,然后在不丢失这次插入的情况下回滚主事务。因为自治事务是与主事务相分离的,所以它不能检测到被修改过的行的当前状态。这就好像在主事务提交之前,它们一直处于单独的会话里,对自治事务来说,它们是不可用的。然而,反过来情况就不同了:主事务能够检测到已经执行过的自治事务的结果。要创建一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQLServer语句都是自治的。触发无法包含COMMIT语句,除非有PRAGMA AUTONOMOUS_TRANSACTION标记。但是,只有触发中的语句才能被提交,主事务则不行。

0b1331709591d260c1c78e86d0c51c18.png

相关文章:

  • ubuntu安装mysql集群_Ubuntu 20.10单机安装MySQL 8.0.22 NDB集群
  • java序列化工具类_java对象序列化及反序列化SerializeUtils工具类
  • java dispatchevent_这段程序的单击事件不能执行,点击后出现如下错误:at java.awt.Component.dispatchEventImpl(Unknown Sou...
  • java kerberos配置_为kerberos配置Storm
  • java nodelist 快速排序_数据结构的实践心得(归并排序和快速排序:mergeSort、quickSort)...
  • java xml setdoctype_集合Set映射一对多(使用xml文件)
  • java dofinalize_Java finalize方法使用
  • java调用ecdh_Jecc(java椭圆曲线加密库)学习笔记及ECDH实现
  • java雷达_Java编写有关雷达问题,哪位高手帮个忙,谢谢~~~
  • 继承java_Java— 继承
  • java guid_细说Java生成GUID的实现方法
  • java多租户_(九十二)java版spring cloud 多租户社交电子商务-gateway(实现限流)...
  • foxpro mysql_Foxpro数据库命令汇总
  • java generatedvalue_java – 在JPA @GeneratedValue列中手动指定主键的值
  • java io byte_JavaIO之字节流学习笔记
  • JS变量作用域
  • LintCode 31. partitionArray 数组划分
  • Magento 1.x 中文订单打印乱码
  • Node + FFmpeg 实现Canvas动画导出视频
  • quasar-framework cnodejs社区
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 不上全站https的网站你们就等着被恶心死吧
  • 对JS继承的一点思考
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 温故知新之javascript面向对象
  • 译米田引理
  • AI算硅基生命吗,为什么?
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 回归生活:清理微信公众号
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #{}和${}的区别?
  • (2)(2.10) LTM telemetry
  • (2.2w字)前端单元测试之Jest详解篇
  • (8)STL算法之替换
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (分布式缓存)Redis持久化
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET和.COM和.CN域名区别
  • .NET微信公众号开发-2.0创建自定义菜单
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @Transactional 竟也能解决分布式事务?
  • [16/N]论得趣
  • [BJDCTF2020]The mystery of ip
  • [Eclipse] 详细设置护眼背景色和字体颜色并导出
  • [ffmpeg] aac 音频编码