当存储过程中发生错误时,重要的是适当处理它,例如:继续或退出当前代码块的执行,并发出有意义的错误消息。其中mysql提供了一种简单的方法来定义处理从一般条件(如警告或异常)到特定条件(例如特定错误代码)的处理程序。完事我们来使用DECLARE HANDLER语句来尝试声明一个处理程序,先来看语法:

DECLARE action HANDLER FOR condition_value statement;

上述sql中,如果条件的值与condition_value匹配,则MySQL将执行statement,并根据该操作继续或退出当前的代码块。其中,操作(action)接受以下值之一:

  • CONTINUE:继续执行封闭代码块(BEGIN ... END)。
  • EXIT:处理程序声明封闭代码块的执行终止。

condition_value指定一个特定条件或一类激活处理程序的条件。condition_value接受以下值之一:

  • 一个MySQL错误代码。
  • 标准SQLSTATE值或者它可以是SQLWARNINGNOTFOUNDSQLEXCEPTION条件,这是SQLSTATE值类的简写。NOTFOUND条件用于游标或SELECT INTO variable_list语句。
  • 与MySQL错误代码或SQLSTATE值相关联的命名条件。

最重要的是,上述sql可以是一个简单的语句或由BEGINEND关键字包围的复合语句。介绍完事之后,咱们来看几个声明处理程序的例子,首先是当程序发生错误时,将has_error变量的值设置为1并继续执行的例子:

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET has_error = 1;

再来看当发生错误时,回滚上一个操作,发出错误消息,并退出当前代码块。 如果在存储过程的BEGIN END块中声明它,则会立即终止存储过程:

DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 'An error has occurred, operation rollbacked and the stored procedure was terminated';
END;

以下处理程序的意思是,如果没有更多的行要提取,在光标或select into语句的情况下,将no_row_found变量的值设置为1并继续执行:

DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_row_found = 1;

以下处理程序如果发生重复的键错误,则会发出MySQL错误1062。 它发出错误消息并继续执行:

DECLARE CONTINUE HANDLER FOR 1062
SELECT 'Error, duplicate key occurred';

上面这些实例可能有点抽象,咱们废话不多说,先来创建一个名为article_tags的新表,来具体操作下:

USE testdb;
CREATE TABLE article_tags(article_id INT,tag_id     INT,PRIMARY KEY(article_id,tag_id)
);

其中呢,article_tags表存储文章和标签之间的关系。每篇文章可能有很多标签,反之亦然。 为了简单起见,我们不会在article_tags表中创建文章(article)表和标签(tags)表以及外键。

完事呢,我们来创建一个存储过程,将文章的id和标签的id插入到article_tags表中:

USE testdb;
DELIMITER $$CREATE PROCEDURE insert_article_tags(IN article_id INT, IN tag_id INT)
BEGINDECLARE CONTINUE HANDLER FOR 1062SELECT CONCAT('duplicate keys (',article_id,',',tag_id,') found') AS msg;-- insert a new record into article_tagsINSERT INTO article_tags(article_id,tag_id)VALUES(article_id,tag_id);-- return tag count for the articleSELECT COUNT(*) FROM article_tags;
END$$
DELIMITER ;

然后呢,我们通过调用insert_article_tags存储过程,为文章ID为1添加标签ID:1,23,如下所示:

CALL insert_article_tags(1,1);
CALL insert_article_tags(1,2);
CALL insert_article_tags(1,3);

我们再尝试插入一个重复的键来检查处理程序是否真的被调用:

CALL insert_article_tags(1,3);

执行上面查询语句,得到以下结果:

mysql> CALL insert_article_tags(1,3);
+----------------------------+
| msg                        |
+----------------------------+
| duplicate keys (1,3) found |
+----------------------------+
1 row in set+----------+
| COUNT(*) |
+----------+
|        3 |
+----------+
1 row in setQuery OK, 0 rows affected

执行后会收到一条错误消息。 但是,由于我们将处理程序声明为CONTINUE处理程序,所以存储过程继续执行。因此,最后获得了文章的标签计数值为:3。来看个图:

但是如果将处理程序声明中的CONTINUE更改为EXIT,那么将只会收到一条错误消息。如下查询语句:

DELIMITER $$CREATE PROCEDURE insert_article_tags_exit(IN article_id INT, IN tag_id INT)
BEGINDECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT 'SQLException invoked';DECLARE EXIT HANDLER FOR 1062 SELECT 'MySQL error code 1062 invoked';DECLARE EXIT HANDLER FOR SQLSTATE '23000'SELECT 'SQLSTATE 23000 invoked';-- insert a new record into article_tagsINSERT INTO article_tags(article_id,tag_id)VALUES(article_id,tag_id);-- return tag count for the articleSELECT COUNT(*) FROM article_tags;
END $$
DELIMITER ;

执行上面查询语句,得到以下结果:

mysql> CALL insert_article_tags_exit(1,3);
+-------------------------------+
| MySQL error code 1062 invoked |
+-------------------------------+
| MySQL error code 1062 invoked |
+-------------------------------+
1 row in setQuery OK, 0 rows affected

来看个图感受下:

如果我们使用多个处理程序来处理错误,MySQL将调用最特定的处理程序来处理错误。这就涉及到优先级的问题了,我们来具体看下。

我们知道错误总是映射到一个MySQL错误代码,因为在MySQL中它是最具体的。 SQLSTATE可以映射到许多MySQL错误代码,因此它不太具体。 SQLEXCPETIONSQLWARNINGSQLSTATES类型值的缩写,因此它是最通用的。假设在insert_article_tags_3存储过程中声明三个处理程序,如下所示:

DELIMITER $$CREATE PROCEDURE insert_article_tags_3(IN article_id INT, IN tag_id INT)
BEGINDECLARE EXIT HANDLER FOR 1062 SELECT 'Duplicate keys error encountered';DECLARE EXIT HANDLER FOR SQLEXCEPTION SELECT 'SQLException encountered';DECLARE EXIT HANDLER FOR SQLSTATE '23000' SELECT 'SQLSTATE 23000';-- insert a new record into article_tagsINSERT INTO article_tags(article_id,tag_id)VALUES(article_id,tag_id);-- return tag count for the articleSELECT COUNT(*) FROM article_tags;
END $$
DELIMITER ;

然后我们尝试通过调用存储过程将重复的键插入到article_tags表中:

CALL insert_article_tags_3(1,3);

如下,可以看到MySQL错误代码处理程序被调用:

mysql> CALL insert_article_tags_3(1,3);
+----------------------------------+
| Duplicate keys error encountered |
+----------------------------------+
| Duplicate keys error encountered |
+----------------------------------+
1 row in setQuery OK, 0 rows affected

完事之后,咱们再来看下使用命名错误条件。从错误处理程序声明开始,如下:

DECLARE EXIT HANDLER FOR 1051 SELECT 'Please create table abc first';
SELECT * FROM abc;

1051号是什么意思? 想象一下,你有一个大的存储过程代码使用了好多类似这样的数字; 这将成为维护代码的噩梦。幸运的是,MySQL为我们提供了声明一个命名错误条件的DECLARE CONDITION语句,它与条件相关联。DECLARE CONDITION语句的语法如下:

DECLARE condition_name CONDITION FOR condition_value;

condition_value可以是MySQL错误代码,例如:1015SQLSTATE值。 condition_valuecondition_name表示。声明后,可以参考condition_name,而不是参考condition_value。所以可以重写上面的代码如下:

DECLARE table_not_found CONDITION for 1051;
DECLARE EXIT HANDLER FOR  table_not_found SELECT 'Please create table abc first';
SELECT * FROM abc;

这段代码比以前的代码显然更可读,不过我们要注意,条件声明必须出现在处理程序或游标声明之前。

好啦,这次就到这里了。

如果感觉不错的话,请多多点赞支持哦。。。

mysql存储过程之错误处理相关推荐

  1. mysql存储过程捕获错误处理_mysql存储过程之异常处理篇

    mysql存储过程也提供了对异常处理的功能:通过定义HANDLER来完成异常声明的实现 语法如下: DECLARE handler_type HANDLER FOR condition_value[, ...

  2. mysql存储过程语法错误1064_mysql,dos下执行SQL语句创建存储过程出错ERROR 1064 (42000):...

    update1.sql的内容为 DROP PROCEDURE IF EXISTS pcName; CREATE PROCEDURE pcName() BEGIN select 'a'; END; do ...

  3. mysql 存储过程 获取错误,MySQL存储过程相互调用并获得错误码示例

    代码如下: mysql> mysql> delimiter $$ mysql> mysql> CREATE PROCEDURE myProc() -> MODIFIES ...

  4. mysql的游标处理_MySQL存储过程 游标 错误处理的示例代码

    MySQL存储过程 游标 错误处理的示例代码--set_account_data 重新生成用户编号 BEGIN DECLARE temp_id INT(8); /*用户id*/ DECLARE tem ...

  5. php保存成乱序,php – 调用MySQL存储过程时出现乱序错误

    我正在尝试使用PDO调用存储过程,但在尝试对结果进行获取时遇到以下错误. 警告:数据包乱序.预计1收到16.数据包大小= 163 我的存储过程使用两个游标,我在从临时表中选择之前关闭它.我怀疑这可能是 ...

  6. jdbc mysql 存储过程执行失败_JDBC连接执行MySQL存储过程报空指针或权限错误

    JDBC连接执行MySQL存储过程报空指针或权限错误 最近使用root用户编写了几个存储过程,但是使用普通用户通过JDBC连接执行却报错: java.lang.NullPointerException ...

  7. mysql 存储过程 错误码_mysql存储过程中的错误处理_mysql

    mysql存储过程中的异常处理 http://www.cnblogs.com/cookiehu/p/4994278.html 定义异常捕获类型及处理方法: DECLAREhandler_action ...

  8. MySQL 存储过程初研究

    最近在做一个移动设备多类型登录的统一用户系统.其中记录用户资料的部分,因为涉及到更换设备的相同用户.同一个用户多类型同时具备的情况,所以想分辨出尽量少的用户去合理记录,就需要多次查询.于是决定研究一下 ...

  9. MySQL 存储过程 经常使用语法

    MySQL 存储过程是从 MySQL 5.0 開始添加的新功能.存储过程的长处有一箩筐.只是最基本的还是运行效率和SQL 代码封装.特别是 SQL 代码封装功能,假设没有存储过程,在外部程序訪问数据库 ...

最新文章

  1. COMMIT WORK AND WAIT 是在WAIT什么
  2. php函数剩余时间,php计算剩余时间的自定义函数
  3. 《Pro Android Graphics》读书笔记之第二节
  4. 两步操作解决Python3中openCV库安装难题(清华大学镜像源)
  5. redis实现session共享,哨兵
  6. 【完全开源】微信客户端.NET版
  7. PCB,硬件工程师的小情人。
  8. Realsense安装使用过程问题汇总
  9. go - range
  10. 实验板FPGA型号在哪里看_项目分享| 自制FPGA最小系统板(PCB可直接打板)
  11. 查看java/jdk版本
  12. 经纬度转换,度转度分秒,度分秒转为度,前端js
  13. SVN 忽略不需要提交的文件
  14. 【TCP/IP 四 IP 网际协议】
  15. 查看 PCD 点云 windows
  16. 金蝶系统登不上服务器270,电脑进不了金蝶软件,显示Automation错误270
  17. 论文解读(PairNorm)《PairNorm: Tackling Oversmoothing in GNNs》
  18. 常用排序:冒泡排序与快速排序详解,看完这篇就够了!风马博客
  19. vue组件库介绍以及组件库Element UI 的使用
  20. 数据结构二叉树的链式存储

热门文章

  1. 高质增长,全年盈利!2022年京东业绩报告来了!
  2. 教你如何安慰失戀人?
  3. python转写java踩坑记录
  4. 动态规划的最优原理与无后效性解析
  5. [GridView]在 RowCommand事件中,自订的Button 如何取出某一列的索引值(RowIndex)
  6. UTF-8编码的原理
  7. Web2.0的系统架构与六大关键问题
  8. php商品浏览页面,jquery仿京东商品放大浏览页面_实例分享
  9. BUUCTF [GXYCTF2019]Ping Ping Ping 1
  10. MySQL 索引介绍!