MySQL存储过程中的错误处理

MySQL存储过程中的错误处理

       当MySQL执行存储过程遇到错误时,适当处理它,如继续执行或退出当前代码段,并返回有意义的错误提示是很重要的。一方面提高程序的容错能力,另一方便当程序出错时,开发人员也能准确定位错误的地方。

在本章MySQL教程中,我们将学习如何在存储过程中处理程序错误


声明处理程序

MySQL为我们提供了一种简单的方法定义处理程序,我们可以使用DECLARE HANDLER语句,如下所示:

1
DECLARE  action  HANDLER  FOR  condition_value statement;

如果其值与condition_value匹配,MySQL将执行statement,并且根据action值选择继续或退出当前代码块。

action 可以是以下两种:

  • CONTINUE:继续执行当前代码块

  • EXIT:退出当前代码块

condition_value 是一类特定的条件,可以使一下几种:

  • 一个MYSQL错误代码

  • 一个标准的SQLSTATE值,如SQLWARNING,NOTFOUND ,SQLEXCEPTION等

statement 是一个语句块,从BEGIN开始,到END结束。它可以是一个简单的sql语句,也可以是很复杂的逻辑语句。


MySQL错误处理的例子

例1:当程序发生错误,将has_error值置为1。如:

1
DECLARE  CONTINUE  HANDLER  FOR  SQLEXCEPTION  SET  has_error = 1;


例2:当遇到错误时,程序将回滚之前的操作,同时给出错误提示,然后退出当前程序块。如:

1
2
3
4
5
DECLARE  EXIT HANDLER  FOR  SQLEXCEPTION
BEGIN
ROLLBACK ;
Select  '发生错误,执行将被回滚,程序将终止执行' ;
END ;


例3:对于游标或select into操作,如果出现找不到记录的情况,将no_row_found赋值为1。如:

1
DECLARE  CONTINUE  HANDLER  FOR  NOT  FOUND  SET  no_row_found = 1;


例4:如果出现重复键值,MySQL会给出1062的错误,将给出错误提示,程序继续运行。如:

1
2
DECLARE  CONTINUE  HANDLER  FOR  1062
Select  '错误:重复键值' ;


在存储过程中MySQL的处理程序的例子

首先我们创建一张数据表,为测试所用。

1
2
3
4
5
Create  TABLE  article_tags(
     article_id  INT ,
     tag_id      INT ,
     PRIMARY  KEY (article_id,tag_id)
);

article_tags表用来存储文章及标签之间的关系(多对多)。article_id存储文章ID,tag_id存储标签ID


其次,我们创建一个存储过程,实现插入文章ID和标签ID。

1
2
3
4
5
6
7
8
9
10
11
DELIMITER $$
Create  PROCEDURE  insert_article_tags( IN  article_id  INT IN  tag_id  INT )
BEGIN
     DECLARE  CONTINUE  HANDLER  FOR  1062
     Select  CONCAT( '错误:重复键值 (' ,article_id, ',' ,tag_id, ')' AS  msg;
     -- 插入新的记录
     Insert  INTO  article_tags(article_id,tag_id)
     VALUES (article_id,tag_id);
     -- 返回标签数量
     Select  COUNT (*)  FROM  article_tags;
END


第三,利用存储过程往article_tags表添加一些数据

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


第四,这一步,我们添加一条已经存在的数据,看看上面定义的错误处理会不会执行。

1
CALL insert_article_tags(1,3);

执行这条语句后,我们会看到如下的错误提示。但是,因为在错误处理程序中我们设置了CONTINUE,因此程序还会继续执行,所以最后我们还会看到标签的数量。如下图:

如果我们将CONTINUE改为EXIT,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DELIMITER $$
Create  PROCEDURE  insert_article_tags_2( IN  article_id  INT IN  tag_id  INT )
BEGIN
     DECLARE  EXIT HANDLER  FOR  SQLEXCEPTION
     Select  'SQLException异常调用'  AS  msg;
     DECLARE  EXIT HANDLER  FOR  1062
         Select  'MySQL错误代码:1062'  AS  msg;
     DECLARE  EXIT HANDLER  FOR  SQLSTATE  '23000'
     Select  'SQLSTATE:23000'  AS  msg;
     -- 插入数据
     Insert  INTO  article_tags(article_id,tag_id)
        VALUES (article_id,tag_id);
     -- 返回记录数
     Select  COUNT (*)  FROM  article_tags;
END

现在,我们再次插入一条已存在的数据:

1
CALL insert_article_tags_2(1,3);

这时,我们将智能看到错误信息,而看不到返回的记录数。


MySQL处理程序的优先级

在实际开发过程中,肯定会有多个错误处理程序,此时MySQL就需要根据优先级来调用处理。

在MySQL中,每一个error错误都会对应一个错误代码,一个SQLSTATE状态可以映射到MySQL多个错误代码,不太具体,而像SQLEXCPETION或SQLWARNING是一类SQLSTATES值,是通用的。因此,在处理优先级上,error错误首先处理,其次是SQLSTATE,最后是SQLEXCEPTION。


下面我们看一个包含这三种错误的存储过程:

1
2
3
4
5
6
7
8
9
10
11
12
ELIMITER $$
Create  PROCEDURE  insert_article_tags_3( IN  article_id  INT IN  tag_id  INT )
BEGIN
     DECLARE  EXIT HANDLER  FOR  1062  Select  '键值重复' ;
     DECLARE  EXIT HANDLER  FOR  SQLEXCEPTION  Select  'SQLException异常' ;
     DECLARE  EXIT HANDLER  FOR  SQLSTATE  '23000'  Select  'SQLSTATE 23000' ;
     -- 插入记录
     Insert  INTO  article_tags(article_id,tag_id)
     VALUES (article_id,tag_id);
     -- 返回记录数
     Select  COUNT (*)  FROM  article_tags;
END

现在,我们插入一条已经存在的记录:

1
CALL insert_article_tags_3(1,3);

按照上面介绍的处理顺序,此时应该提示“键值重复”。如下图:


命名错误

首先我们看一个例子:

1
2
DECLARE  EXIT HANDLER  FOR  1051  Select  '请先创建数据表 abc' ;
Select  FROM  abc;

当我们查询一张不存在的的表时,提示相关错误信息,这里我们用到了1051代码。想想一下,MySQL中有相当多的错误代码,难道我们需要记住每一个吗?

当然不是,MySQL为我们提供了DECLARE CONDITION语句,用于命名错误条件,如:

1
DECLARE  condition_name CONDITION  FOR  condition_value;

condition_value是一个错误代码,如1015或SQLSTATE值。

定义之后,我们就可以使用condition_name来代替condition_value。现在,我们将上面的脚本重写,如:

1
2
3
DECLARE  table_not_found CONDITION  for  1051;
DECLARE  EXIT HANDLER  FOR   table_not_found  Select  '请先创建数据表 abc' ;
Select  FROM  abc;

很显然,这段代码可读性比上面的要好。


原文(英文)地址:http://www.mysqltutorial.org/mysql-error-handling-in-stored-procedures/



http://www.uncletoo.com/html/mysql/953.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值