MySQL的存储过程错误捕获方式和Oracle的有很大的不同。

MySQL中可以使用DECLARE关键字来定义处理程序。其基本语法如下:

DECLARE handler_type HANDLER FOR condition_value[,...] sp_statement 

handler_type: CONTINUE | EXIT  

condition_value:
SQLSTATE [VALUE] sqlstate_value |
condition_name |
SQLWARNING |
NOT FOUND |
SQLEXCEPTION |
mysql_error_code

handler_type参数指明错误的处理方式,该参数有2个取值。这1个取值分别是CONTINUE、EXIT

CONTINUE表示遇到错误,执行预先定义的方式,继续向下执行;

EXIT表示遇到错误后,执行预先定义的方式,马上退出;

注意:通常情况下,执行过程中遇到错误应该立刻停止执行下面的语句,并且撤回前面的操作。

condition_value参数指明错误类型,该参数有6个取值。

sqlstate_value和mysql_error_code与条件定义中的是同一个意思。

condition_name是DECLARE定义的条件名称。

SQLWARNING表示所有以01开头的sqlstate_value值。

NOT FOUND表示所有以02开头的sqlstate_value值。

SQLEXCEPTION表示所有没有被SQLWARNING或NOT FOUND捕获的sqlstate_value值。

sp_statement表示一些存储过程或函数的执行语句。

下面是定义处理程序的几种方式。代码如下:

//方法一:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE ''
SET @info='CAN NOT FIND';
//方法二:捕获mysql_error_code
DECLARE CONTINUE HANDLER FOR 1148SET @info='CAN NOT FIND';
//方法三:先定义条件,然后调用
DECLARE can_not_find CONDITION FOR 1146 ;
DECLARE CONTINUE HANDLER FOR can_not_find SET
@info='CAN NOT FIND';
//方法四:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';
//方法五:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info='CAN NOT FIND';
//方法六:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';

上述代码是6种定义处理程序的方法。

第一种方法是捕获sqlstate_value值。如果遇到sqlstate_value值为42000,执行CONTINUE操作,并且输出"CAN NOT FIND"信息。

第二种方法是捕获mysql_error_code值。如果遇到mysql_error_code值为1148,执行CONTINUE操作,并且输出"CAN NOT FIND"信息。

第三种方法是先定义条件,然后再调用条件。这里先定义can_not_find条件,遇到1148错误就执行CONTINUE操作。

第四种方法是使用SQLWARNING。SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行EXIT操作,并且输出"ERROR"信息。

第五种方法是使用NOT FOUND。NOT FOUND捕获所有以02开头的sqlstate_value值,然后执行EXIT操作,并且输出"CAN NOT FIND"信息。

第六种方法是使用SQLEXCEPTION。SQLEXCEPTION捕获所有没有被SQLWARNING或NOT FOUND捕获的sqlstate_value值。

单句的

DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_row_found = 1;
DECLARE CONTINUE HANDLER FOR 1062
SELECT 'Error, duplicate key occurred';

如果错误捕获的时候要做的操作比较多可以这样

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

example:

CREATE TABLE `article_tags` (
`article_id` int(11) NOT NULL DEFAULT '',
`tag_id` int(11) NOT NULL DEFAULT '',
PRIMARY KEY (`article_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DELIMITER $$

CREATE PROCEDURE insert_article_tags(IN article_id INT, IN tag_id INT)
BEGIN DECLARE CONTINUE HANDLER FOR 1062
SELECT CONCAT('duplicate keys (',article_id,',',tag_id,') found') AS msg; -- insert a new record into article_tags
INSERT INTO article_tags(article_id,tag_id)
VALUES(article_id,tag_id); -- return tag count for the article
SELECT COUNT(*) FROM article_tags;
END

mysql 抛出错误给调用程序

使用signal语句返回Error或warning给存储过程的调用者。

signal的语法:

SIGNAL SQLSTATE | condition_name
SET condition_information_item_name_1 = value_1,
condition_information_item_name_1 = value_2, etc;

使用SET设置返回的内容,如果要返回多个条件信息用逗号隔开。

RESIGNAL无论是功能上还是用法上和signal都很像,除了:

  1.使用resignal的时候必须配合handler使用,否则会得到 “RESIGNAL when handler is not active”的报错,

然而signal可以在存储过程的任何地方使用。

  2.可以漏掉resignal语句的所有属性,甚至是SQLSTATE value.

DELIMITER $$

CREATE PROCEDURE AddOrderItem(
in orderNo int,
in productCode varchar(45),
in qty int,
in price double,
in lineNo int )
BEGIN
DECLARE C INT; SELECT COUNT(orderNumber) INTO C
FROM orders
WHERE orderNumber = orderNo; -- check if orderNumber exists
IF(C != 1) THEN
SIGNAL SQLSTATE ''
SET MESSAGE_TEXT = 'Order No not found in orders table';
END IF;
-- more code below
-- ...
END
DELIMITER $$

CREATE PROCEDURE Divide(IN numerator INT, IN denominator INT, OUT result double)
BEGIN
DECLARE division_by_zero CONDITION FOR SQLSTATE ''; DECLARE CONTINUE HANDLER FOR division_by_zero
RESIGNAL SET MESSAGE_TEXT = 'Division by zero / Denominator cannot be zero';
--
IF denominator = 0 THEN
SIGNAL division_by_zero;
ELSE
SET result := numerator / denominator;
END IF;
END

没有resignal 的时候调用存储过程:

DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_article_tags`(IN article_id INT, IN tag_id INT)
BEGIN DECLARE CONTINUE HANDLER FOR 1062
begin
insert into pro_log values('',CONCAT('duplicate keys (',article_id,',',tag_id,') found'));
SELECT CONCAT('duplicate keys (',article_id,',',tag_id,') found') AS msg;
-- resignal set message_text ='duplicate keys';
end ; -- declare continue handler for sqlexception
-- SELECT 'SQLException invoked'; -- insert a new record into article_tags
INSERT INTO article_tags(article_id,tag_id)
VALUES(article_id,tag_id); -- return tag count for the article
SELECT
COUNT(*)
FROM
article_tags; END

测试调用

去掉注释的 resignal set。

继续测试

这样可以得到向外抛出的错误。

参考:

http://www.mysqltutorial.org/mysql-error-handling-in-stored-procedures/

http://www.mysqltutorial.org/mysql-signal-resignal/

http://www.cnblogs.com/lyhabc/p/3793524.html

http://www.zhdba.com/mysqlops/2013/08/31/mysql-handler-2/

mysql Error Handling and Raising in Stored Procedures的更多相关文章

  1. MySQL Error Handling in Stored Procedures 2

    Summary: this tutorial shows you how to use MySQL handler to handle exceptions or errors encountered ...

  2. MySQL Error Handling in Stored Procedures---转载

    This tutorial shows you how to use MySQL handler to handle exceptions or errors encountered in store ...

  3. MySQL Error Handling in Stored Procedures

    http://www.mysqltutorial.org/mysql-error-handling-in-stored-procedures/ mysql存储过程中的异常处理   定义异常捕获类型及处 ...

  4. An Introduction to Stored Procedures in MySQL 5

    https://code.tutsplus.com/articles/an-introduction-to-stored-procedures-in-mysql-5--net-17843 MySQL ...

  5. Home / Python MySQL Tutorial / Calling MySQL Stored Procedures in Python Calling MySQL Stored Procedures in Python

    f you are not familiar with MySQL stored procedures or want to review it as a refresher, you can fol ...

  6. Cursors in MySQL Stored Procedures

    https://www.sitepoint.com/cursors-mysql-stored-procedures/ After my previous article on Stored Proce ...

  7. [MySQL] Stored Procedures 【转载】

    Stored routines (procedures and functions) can be particularly useful in certain situations: When mu ...

  8. MySql Error: Can't update table in stored function/trigger

    MySql Error: Can't update table in stored function/trigger because it is already used by statement w ...

  9. Good Practices to Write Stored Procedures in SQL Server

    Reference to: http://www.c-sharpcorner.com/UploadFile/skumaar_mca/good-practices-to-write-the-stored ...

随机推荐

  1. mysql 高可用方案漫谈(一) 转阿里云

    https://yq.aliyun.com/articles/2237?spm=5176.blog2238.yqblogcon1.7.e5fyEy#index_section

  2. ibdata文件增大的原因

    http://blog.itpub.net/22664653/viewspace-1994016/

  3. Android 开发中的屏幕适配技术详解

    本文主要介绍Android开发中比较头疼繁琐的一个问题-屏幕适配问题.主要从适配原因.基本核心概念.适配方法等方面介详细 介绍从而是的深入或者进一步对Android屏幕适配技术的掌握和理解. 真题园网 ...

  4. Spring-boot访问MongoDB

    1.访问配置信息 package hello; import org.springframework.context.annotation.Bean; import org.springframewo ...

  5. Unix网络编程(1)——socket一窥

    套接口地址结构 IPv4的套接口地址结构为: struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; struct in_addr ...

  6. 想做一个整合开源安全代码扫描工具的代码安全分析平台 - Android方向调研

    想做一个整合开源安全代码扫描工具的代码安全分析平台 - Android方向调研 http://blog.csdn.net/testing_is_believing/article/details/22 ...

  7. Oracle inactive session (last_call_et)

    注意last_call_et的值, select s.status,s.last_call_et,s.* from v$session s where username='DDD'; 在本例中,开了个 ...

  8. 关于国际化中的$NON-NLS-1$

    百度百科解释: 这实际与eclipse中支持i18n的一种方式,eclipse的标准结构,将所有string常量定义到·properties中,例如下面程序段中的TestRef.hello实际上是·p ...

  9. Java读取一个文件并打印到控制台上

    package test9; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundExcept ...

  10. The Shapes of CSS

    #square { width: 100px; height: 100px; background: red; } #rectangle { width: 200px; height: 100px; ...