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
}
该DECLARE ...
HANDLER
语句指定处理一个或多个条件的处理程序。如果这些条件之一发生,则statement
执行指定的。
statement
可以是简单的语句,例如, 或使用and
编写的复合语句(请参阅第 13.6.1 节,“BEGIN ... END 复合语句”)。
SET
var_name
=
value
BEGIN
END
处理程序声明必须出现在变量或条件声明之后。
该handler_action
值指示处理程序在执行处理程序语句后采取的操作:
CONTINUE
:继续执行当前程序。EXIT
BEGIN ... END
:对于声明处理程序的复合语句,执行终止 。即使条件发生在内部块中也是如此。UNDO
: 不支持。
condition_value
for
DECLARE ...
HANDLER
指示激活处理程序的特定条件或条件类别
。它可以采用以下形式:
mysql_error_code
:表示MySQL错误代码的整数文字,例如1051表示“未知表”:DECLARE CONTINUE HANDLER FOR 1051 BEGIN -- body of handler END;
不要使用 MySQL 错误代码 0,因为它表示成功而不是错误情况。有关 MySQL 错误代码的列表,请参阅服务器错误消息参考。
SQLSTATE [VALUE]
sqlstate_value
:一个 5 个字符的字符串文字,表示一个 SQLSTATE 值,例如'42S01'
指定“未知表”:DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' BEGIN -- body of handler END;
不要使用以 开头的 SQLSTATE 值,
'00'
因为这些值表示成功而不是错误情况。有关 SQLSTATE 值的列表,请参阅服务器错误消息参考。condition_name
: 之前用 指定的条件名称DECLARE ... CONDITION
。条件名称可以与 MySQL 错误代码或 SQLSTATE 值相关联。请参阅 第 13.6.7.1 节,“DECLARE ... CONDITION 语句”。SQLWARNING
: 以 开头的 SQLSTATE 值类的简写'01'
。DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN -- body of handler END;
NOT FOUND
: 以 开头的 SQLSTATE 值类的简写'02'
。这在游标上下文中是相关的,用于控制游标到达数据集末尾时发生的情况。如果没有更多行可用,则出现 No Data 条件,SQLSTATE value'02000'
。要检测此条件,您可以为其或条件设置一个处理程序NOT FOUND
。DECLARE CONTINUE HANDLER FOR NOT FOUND BEGIN -- body of handler END;
对于另一个示例,请参阅第 13.6.6 节,“游标”。对于未检索任何行
NOT FOUND
的语句,也会出现 这种 情况。SELECT ... INTO
var_list
SQLEXCEPTION
'00'
:不以、'01'
或 开头的 SQLSTATE 值类的简写'02'
。DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN -- body of handler END;
有关在条件发生时服务器如何选择处理程序的信息,请参阅第 13.6.7.6 节,“处理程序的作用域规则”。
如果发生没有声明处理程序的条件,则采取的操作取决于条件类:
以下示例使用处理程序 for SQLSTATE
'23000'
,它针对重复键错误发生:
mysql> CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1));
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter //
mysql> CREATE PROCEDURE handlerdemo ()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET @x2 = 1;
SET @x = 1;
INSERT INTO test.t VALUES (1);
SET @x = 2;
INSERT INTO test.t VALUES (1);
SET @x = 3;
END;
//
Query OK, 0 rows affected (0.00 sec)
mysql> CALL handlerdemo()//
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @x//
+------+
| @x |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
请注意,这@x
是3
在过程执行之后,这表明在发生错误后,执行一直持续到过程结束。如果该
DECLARE ...
HANDLER
语句不存在,MySQL 将在第二次由于约束而
失败EXIT
后采取默认操作 () ,并返回
。
INSERT
PRIMARY KEY
SELECT @x
2
要忽略条件,请为其声明一个CONTINUE
处理程序并将其与一个空块相关联。例如:
DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;
块标签的范围不包括块内声明的处理程序的代码。因此,与处理程序关联的语句不能使用
ITERATE
或
LEAVE
引用包含处理程序声明的块的标签。考虑以下示例,其中
REPEAT
块的标签为
retry
:
CREATE PROCEDURE p ()
BEGIN
DECLARE i INT DEFAULT 3;
retry:
REPEAT
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
ITERATE retry; # illegal
END;
IF i < 0 THEN
LEAVE retry; # legal
END IF;
SET i = i - 1;
END;
UNTIL FALSE END REPEAT;
END;
该retry
标签在
IF
块内语句的范围内。它不在CONTINUE
处理程序的范围内,因此那里的引用无效并导致错误:
ERROR 1308 (42000): LEAVE with no matching label: retry
要避免在处理程序中引用外部标签,请使用以下策略之一:
要离开块,请使用
EXIT
处理程序。如果不需要块清理,则BEGIN ... END
处理程序主体可以为空:DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END;
否则,将清理语句放在处理程序主体中:
DECLARE EXIT HANDLER FOR SQLWARNING BEGIN block cleanup statements END;
要继续执行,请在处理程序中设置一个状态变量
CONTINUE
,可以在封闭块中检查该变量以确定是否调用了处理程序。以下示例done
为此目的使用该变量:CREATE PROCEDURE p () BEGIN DECLARE i INT DEFAULT 3; DECLARE done INT DEFAULT FALSE; retry: REPEAT BEGIN DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN SET done = TRUE; END; IF done OR i < 0 THEN LEAVE retry; END IF; SET i = i - 1; END; UNTIL FALSE END REPEAT; END;