最近在做 SQL Server 到 MySQL 的迁移(migration),相较于对表和数据的迁移,最令人犯难的还是在功能性存储过程脚本的改写转换(convert),虽说 MySQL 如今是蓬勃发展,不断的更新迭代的优化,但是在存储过程等脚本方面与 Oracle、SQL Server 相比,个人感觉是有所欠缺的,无论是灵活性还是实用性,有时真的是很难达到自己想要的效果,或许这就是为什么存储过程在 MySQL 中使用较少的原因吧……

  承接上一篇关于MySQL的异常处理,继续异常处理的扩展性用法:

异常处理语句:

1、DECLARE ... CONDITION …

2、DECLARE ... HANDLER …

3、SIGNAL …

4、RESIGNAL …

5、GET DIAGNOSTICS …

一、常规声明的异常处理

1、条件声明

DECLARE condition_name CONDITION FOR condition_value

condition_value: {
mysql_error_code
| SQLSTATE [VALUE] sqlstate_value
}

  condition_name:标准的变量命名;

  condition_value:SQLSTATE 值或者 MySQL 自身的 ERROR CODE ;

注:单独的 condition 语句不能直接运行,只能作为【条件处理】的一部分。

2、条件处理

DECLARE handler_action HANDLER
FOR condition_value [, condition_value] ...
statement handler_action: {
CONTINUE
| EXIT
| UNDO
} condition_value: {
mysql_error_code
| SQLSTATE [VALUE] sqlstate_value
| condition_name
| SQLWARNING
| NOT FOUND
| SQLEXCEPTION
}

  handler_action:代表处理的动作,常用的是继续(CONTIUE)和直接退出(EXIT);

  condition_value:异常处理捕获条件或情况,包括【条件声明】里的 SQLSTATE, MYSQL EEROR CODE, condition_name 以及范围混淆的其他两种;

注:SQLWARNING、SQLEXCEPTION、NOT FOUND 表示任何不存在的 WARNING 或者 ERROR。

mysql> DESC tab7; 
ERROR 1146 (42S02): Table 'TestDB.tab7' doesn't exist DELIMITER //
CREATE PROCEDURE PROC_1()
BEGIN
DECLARE CONTINUE HANDLER FOR 1146
BEGIN
-- body of handler
END; DECLARE not_exist_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR not_exist_table
BEGIN
-- body of handler
END; DECLARE not_exist_table CONDITION FOR SQLSTATE '42S02';
DECLARE CONTINUE HANDLER FOR not_exist_table
BEGIN
-- body of handler
END;
END //
DELIMITER ;

二、SIGNAL 与 RESIGNAL

  SIGNAL 与 RESIGNAL 可以通过自定义伪装系统的错误信息以及代码,刷新当前警告缓冲区域。

1、SIGNAL

  SIGNAL是“返回”错误的方法,向处理程序,应用程序的外部部分或客户端提供错误信息。

  此外,它还可以控制错误的特征(错误号,SQLSTATE值,消息)。 如果没有SIGNAL,则必须采用诸如故意引用不存在的表之类的解决方法来导致例程返回错误。

SIGNAL condition_value
[SET signal_information_item
[, signal_information_item] ...] condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
} signal_information_item:
condition_information_item_name = simple_value_specification condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}

2、RESIGNAL

  同样的,RESIGNAL 也可以异常处理并返回错误信息。

RESIGNAL [condition_value]
[SET signal_information_item
[, signal_information_item] ...] condition_value: {
SQLSTATE [VALUE] sqlstate_value
| condition_name
} signal_information_item:
condition_information_item_name = simple_value_specification condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}

  通过对比 SIGNAL 与 RESIGNAL 的语法,在使用 SIGNAL 方法的时候必须指定 condition_value ,也就是说其不能单独使用,需要先定义异常处理,可以在存储过程中的任何位置使用 SIGNAL 语句。

  而 RESIGNAL 可以省略RESIGNAL语句的所有属性,甚至可以省略SQLSTATE值,但必须在错误或警告处理程序中使用 RESIGNAL 语句,否则将收到一条错误消息,指出“RESIGNAL when handler is not active”。如果单独使用RESIGNAL语句,则所有属性与传递给条件处理程序的属性相同。

3、常见对比使用实例

DELIMITER //
CREATE PROCEDURE `test_proc`(var1 int,var2 int)
BEGIN
declare ErrorMessage varchar(255) ;
-- SIGNAL Declarations
declare EXP_CONDITION condition for sqlstate 'EX000' ;
declare exit handler for sqlstate 'EX000' begin
signal EXP_CONDITION set message_text = ErrorMessage ;
end ;
-- RESIGNAL Declarations
declare exit handler for sqlstate '42S02' begin
resignal set message_text = 'Unknown tables appear in the process body.' ;
end ;
-- Processing
if( var1 <> var2 ) then
set ErrorMessage = 'The first number input does not equal the second number.' ;
signal EXP_CONDITION set message_text = ErrorMessage ;
end if ;
select * from xxx ; -- unknow table xxx
END //
DELIMITER ;
mysql> call test_proc(1,1);
ERROR 1146 (42S02): Unknown tables appear in the process body.
mysql> call test_proc(1,2);
ERROR 1644 (EX000): The first number input does not equal the second number.

  推荐使用 SIGNAL,灵活随机,在定义好后即可将 SIGNAL 语句放到任何你想放的地方进行判断预警处理。

、GET DIAGNOSTICS

  5.6开始支持的语法,从而获取错误缓冲区的内容,然后把这些内容输出到不同范围域的变量里,以便后续灵活操作处理。

GET [CURRENT | STACKED] DIAGNOSTICS
{
statement_information_item
[, statement_information_item] ...
| CONDITION condition_number
condition_information_item
[, condition_information_item] ...
} statement_information_item:
target = statement_information_item_name condition_information_item:
target = condition_information_item_name statement_information_item_name:
NUMBER
| ROW_COUNT condition_information_item_name: {
CLASS_ORIGIN
| SUBCLASS_ORIGIN
| RETURNED_SQLSTATE
| MESSAGE_TEXT
| MYSQL_ERRNO
| CONSTRAINT_CATALOG
| CONSTRAINT_SCHEMA
| CONSTRAINT_NAME
| CATALOG_NAME
| SCHEMA_NAME
| TABLE_NAME
| COLUMN_NAME
| CURSOR_NAME
}

  statement_information_item:statment 执行情况信息捕获反馈,包括 NUMBER、ROW_COUNT;

  condition_information_item:捕获异常情况信息;

  当条件发生,可以通过变量去接收条件项目信息,但也不是说有的 MySQL 都会进行填充赋值,也会出现空值的(例如:SCHEMA_NAME and TABLE_NAME is null when drop table)。

mysql> delete from t5;
Query OK, 3 rows affected (0.04 sec) mysql> GET DIAGNOSTICS @p3 = NUMBER, @p4 = ROW_COUNT;
Query OK, 0 rows affected (0.00 sec) mysql> select @p3,@p4;
+------+------+
| @p3 | @p4 |
+------+------+
| 0 | 3 |
+------+------+
1 row in set (0.00 sec) mysql> drop table xxx;
ERROR 1051 (42S02): Unknown table 'TestDB.xxx'
mysql> show warnings; -- or show error
+-------+------+----------------------------+
| Level | Code | Message |
+-------+------+----------------------------+
| Error | 1051 | Unknown table 'TestDB.xxx' |
+-------+------+----------------------------+
1 row in set (0.00 sec) mysql> GET DIAGNOSTICS CONDITION 1
-> @p1 = RETURNED_SQLSTATE, @p2 = MESSAGE_TEXT;
Query OK, 0 rows affected (0.00 sec) mysql> select @p1,@p2;
+-------+----------------------------+
| @p1 | @p2 |
+-------+----------------------------+
| 42S02 | Unknown table 'TestDB.xxx' |
+-------+----------------------------+
1 row in set (0.00 sec)

注:个人认为,因为使用 GET DIAGNOSTICS 略有些鸡肋,使用选择上更多的会是用 SIGNAL 语句进行异常处理,所以在此不做深究 GET DIAGNOSTICS 的使用。

MySQL-[SIGNAL/RESIGNAL/GET DIAGNOSTICS]的使用的更多相关文章

  1. Raising Error Conditions with MySQL SIGNAL / RESIGNAL Statements

    http://www.mysqltutorial.org/mysql-signal-resignal/ Summary: in this tutorial, you will learn how to ...

  2. MySQL存储过程整理

    MySQL存储过程 2018-08-15  23:00:06 1.存储过程介绍 (1) 定义:存储过程是存储在数据库目录中的一段声明性SQL语句. 触发器,其他存储过程以及java,python,ph ...

  3. (转)mysql各个主要版本之间的差异

    原文:http://blog.csdn.net/z1988316/article/details/8095407   一.各版本的常用命令差异 show innodb status\G mysql-5 ...

  4. MySQL 4.1-5.0-5.1-5.5-5.6各版本的主要区别

    各版本的一些命令差异:  show innodb status\G mysql-5.1  show engines innodb status\G mysql-5.5  关于grant授权 mysql ...

  5. MYSQL的历史

    MYSQL的历史 见证MySQL发展历程 各分支版本溯源 http://tech.it168.com/a2012/0621/1363/000001363446.shtml [IT168 技术]毫无疑问 ...

  6. MySql与MariaDB由来与历程

    MySQL数据库 MySQL数据库是一个关系型数据库管理系统,由瑞典MySQL AB公司开发.MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这 ...

  7. 【Mysql】Mysql 各个版本区别

    一.Mysql 各个版本区别: 1.MySQL Community Server 社区版本,开源免费,但不提供官方技术支持.这也是我们通常用的MySQL的版本.根据不同的操作系统平台细分为多个版本 2 ...

  8. 学习笔记:The Best of MySQL Forum

    http://mysql.rjweb.org/bestof.html I have tagged many of the better forum threads. 'Better' is based ...

  9. mysql数据库( 基础篇加破解)

    1.数据库(Database,DB)是按照数据结构来组织.存储和管理数据的,并且是建立在计算机存储设备上的仓库 2.什么是数据库:(用来存储数据的仓库) 数据库:(cs架构套接字) 数据库管理软件分类 ...

随机推荐

  1. Class "xxxxx"defined without specifying a base class

    解决方法: 导入#import xxxx.h即可 程序需要了解整个类.所以需要添加 #import xxxx.h

  2. quick Cocos 2dx 学习网站

    http://quick.cocoachina.com/wiki/doku.php?id=zh_cn http://www.cocoachina.com/ http://www.cocoachina. ...

  3. Deepin 15.4 升级 chrome flash

    到 adobe 官方下载 flash插件 flash_player_ppapi_linux ~/.config/google-chrome/PepperFlash下建个目录 23.0.0.185,把 ...

  4. JS中的算法与数据结构——排序(Sort)

    排序算法(Sort) 引言 我们平时对计算机中存储的数据执行的两种最常见的操作就是排序和查找,对于计算机的排序和查找的研究,自计算机诞生以来就没有停止过.如今又是大数据,云计算的时代,对数据的排序和查 ...

  5. 【springboot】【redis】springboot+redis实现发布订阅功能,实现redis的消息队列的功能

    springboot+redis实现发布订阅功能,实现redis的消息队列的功能 参考:https://www.cnblogs.com/cx987514451/p/9529611.html 思考一个问 ...

  6. HashMap代码解析

    hashmap (jdk 1.7)使用 “数组-链表” 方式进行存储,图形化表示如下: 即,前面是一个数组,后面跟一个链表,那么数据结构这个对应到HashMap的代码里面是什么样子的呢? 在HashM ...

  7. 转 信号量与PV操作

    在计算机操作系统中,PV操作是进程管理中的难点.首先应弄清PV操作的含义:PV操作由P操作原语和V操作原语组成(原语是不可中断的过程),对信号量进行操作,具体定义如下:    P(S):①将信号量S的 ...

  8. 只有设置了 name 属性的表单元素才能在提交表单时传递它们的值

    $(function () { var wait = $("<img src=\"\" alt=\"正在上传\"/>"); $( ...

  9. 【C#】解析C#中管道流的使用

    目录结构: contents structure [+] 匿名管道(anonymous pipe) 命名管道(named pipe) 管道为进程间通信提供了一种可能.管道分为两种,一种是匿名管道,另一 ...

  10. Oracle&SQLServer中实现跨库查询

    一.在SQLServer中连接另一个SQLServer库数据 在SQL中,要想在本地库中查询另一个数据库中的数据表时,可以创建一个链接服务器: EXEC master.dbo.sp_addlinked ...