mysql resignal_MySQL-[SIGNAL/RESIGNAL/GET DIAGNOSTICS]的使用

本文介绍了在MySQL中进行异常处理的扩展方法,重点讲解了SIGNAL和RESIGNAL的使用,以及GET DIAGNOSTICS的简单应用。在SQL Server到MySQL的迁移过程中,遇到存储过程转换的挑战,特别是MySQL在异常处理上的灵活性。通过示例展示了如何定义条件声明、处理异常、自定义错误信息以及如何捕获和传递错误状态。
摘要由CSDN通过智能技术生成

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

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

一、常规声明的异常处理

1、条件声明

AAffA0nNPuCLAAAAAElFTkSuQmCCDECLARE condition_name CONDITION FOR condition_value

condition_value: {

mysql_error_code  | SQLSTATE [VALUE] sqlstate_value

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

condition_name:标准的变量命名;

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

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

2、条件处理

AAffA0nNPuCLAAAAAElFTkSuQmCCDECLARE 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

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

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

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

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

AAffA0nNPuCLAAAAAElFTkSuQmCCmysql> 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 ;

AAffA0nNPuCLAAAAAElFTkSuQmCC

二、SIGNAL 与 RESIGNAL

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

1、SIGNAL

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

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

AAffA0nNPuCLAAAAAElFTkSuQmCCSIGNAL 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

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

2、RESIGNAL

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

AAffA0nNPuCLAAAAAElFTkSuQmCCRESIGNAL [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

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

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

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

3、常见对比使用实例

AAffA0nNPuCLAAAAAElFTkSuQmCCDELIMITER //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 xxxEND //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.

AAffA0nNPuCLAAAAAElFTkSuQmCC

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

三、GET DIAGNOSTICS

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

AAffA0nNPuCLAAAAAElFTkSuQmCCGET [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

}

AAffA0nNPuCLAAAAAElFTkSuQmCC

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

condition_information_item:捕获异常情况信息;

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

AAffA0nNPuCLAAAAAElFTkSuQmCCmysql> 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)

AAffA0nNPuCLAAAAAElFTkSuQmCC

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

以下是 MySQL 的所有关键字列表: - ADD - ALL - ALTER - ANALYZE - AND - AS - ASC - ASENSITIVE - BEFORE - BETWEEN - BIGINT - BINARY - BLOB - BOTH - BY - CALL - CASCADE - CASE - CHANGE - CHAR - CHARACTER - CHECK - COLLATE - COLUMN - CONDITION - CONSTRAINT - CONTINUE - CONVERT - CREATE - CROSS - CURRENT_DATE - CURRENT_TIME - CURRENT_TIMESTAMP - CURRENT_USER - CURSOR - DATABASE - DATABASES - DAY_HOUR - DAY_MICROSECOND - DAY_MINUTE - DAY_SECOND - DEC - DECIMAL - DECLARE - DEFAULT - DELAYED - DELETE - DESC - DESCRIBE - DETERMINISTIC - DISTINCT - DISTINCTROW - DIV - DOUBLE - DROP - DUAL - EACH - ELSE - ELSEIF - ENCLOSED - ESCAPED - EXISTS - EXIT - EXPLAIN - FALSE - FETCH - FLOAT - FLOAT4 - FLOAT8 - FOR - FORCE - FOREIGN - FROM - FULLTEXT - GENERATED - GET - GRANT - GROUP - HAVING - HIGH_PRIORITY - HOUR_MICROSECOND - HOUR_MINUTE - HOUR_SECOND - IF - IGNORE - IN - INDEX - INFILE - INNER - INOUT - INSENSITIVE - INSERT - INT - INT1 - INT2 - INT3 - INT4 - INT8 - INTEGER - INTERVAL - INTO - IO_AFTER_GTIDS - IO_BEFORE_GTIDS - IS - ITERATE - JOIN - KEY - KEYS - KILL - LEADING - LEAVE - LEFT - LIKE - LIMIT - LINEAR - LINES - LOAD - LOCALTIME - LOCALTIMESTAMP - LOCK - LONG - LONGBLOB - LONGTEXT - LOOP - LOW_PRIORITY - MASTER_BIND - MASTER_SSL_VERIFY_SERVER_CERT - MATCH - MAXVALUE - MEDIUMBLOB - MEDIUMINT - MEDIUMTEXT - MIDDLEINT - MINUTE_MICROSECOND - MINUTE_SECOND - MOD - MODIFIES - NATURAL - NOT - NO_WRITE_TO_BINLOG - NULL - NUMERIC - ON - OPTIMIZE - OPTION - OPTIONALLY - OR - ORDER - OUT - OUTER - OUTFILE - PARTITION - PERIOD_ADD - PERIOD_DIFF - PRIMARY - PROCEDURE - PURGE - RANGE - READ - READS - READ_WRITE - REAL - REFERENCES - REGEXP - RELEASE - RENAME - REPEAT - REPLACE - REQUIRE - RESIGNAL - RESTRICT - RETURN - REVOKE - RIGHT - RLIKE - ROW - ROWS - ROW_COUNT - SCHEMA - SCHEMAS - SECOND_MICROSECOND - SELECT - SENSITIVE - SEPARATOR - SET - SHOW - SIGNAL - SLOW - SMALLINT - SPATIAL - SPECIFIC - SQL - SQL_BIG_RESULT - SQL_CALC_FOUND_ROWS - SQL_SMALL_RESULT - SQLEXCEPTION - SQLSTATE - SQLWARNING - SSL - STARTING - STORED - STRAIGHT_JOIN - TABLE - TERMINATED - THEN - TINYBLOB - TINYINT - TINYTEXT - TO - TRAILING - TRIGGER - TRUE - UNDO - UNION - UNIQUE - UNLOCK - UNSIGNED - UPDATE - USAGE - USE - USING - UTC_DATE - UTC_TIME - UTC_TIMESTAMP - VALUES - VARBINARY - VARCHAR - VARCHARACTER - VARYING - WHEN - WHERE - WHILE - WITH - WRITE - XOR - YEAR_MONTH - ZEROFILL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值