DECLARE HANDLER
语法
DECLARE handler_type HANDLER FOR condition_value [, condition_value] ... statement handler_type: CONTINUE | EXIT | UNDO condition_value: SQLSTATE [VALUE] sqlstate_value | condition_name | SQLWARNING | NOT FOUND | SQLEXCEPTION | mariadb_error_code
描述
DECLARE ... HANDLER
语句定义一个handler,它可以处理一个或多个条件。当一个或多个条件被触发时,将执行指定的语句。所执行的语句可以是一个简单的语句(例如SET var_name=value
),也可以是BEGIN...END
的语句块。
handler必须定义在本地变量、CONDITION
或游标之后。
对于CONTINUE
类的handler,会在退出handler语句的时候继续执行当前程序。对于EXIT
类型的handler,将在执行完BEGIN...END
(如果有)后退出。目前不支持UNDO
类型的handler。
如果condition发生了,但却没有为此condition声明handler,则默认的处理类型为EXIT
。
其中condition_value的值可以是以下几种:
- 一个SQLSTATE值(5个字符的字符串)或MariaDB的错误代码(一个数值)。不能使用"00000"或错误代码0,因为这是执行成功的状态码而不是失败状态码。
SQLSTATE
和MariaDB的错误代码列表见:MariaDB Error Codes。 - 在此之前使用
DECLARE ... CONDITION
声明的condition名称。这个condition必须是声明在同一个存储程序中的。见:DECLARE CONDITION。 SQLWARNING
,它是以'01'开头的特殊SQLSTATE
。NOT FOUND
,它是以'02'开头的特殊SQLSTATE
。这仅使用与游标上下文,用来控制游标到达数据集的尾部时的处理方式。如果游标无法获取更多的数据,它将返回一个02000的SQLSTATE
,藉此,你可以设置一个handler来处理这种情况。在Cursor Overview中给出了一个处理游标的handler。这也适用于SELECT...INTO var_list
语句,当它没有更多行可以获取时就会返回这样的SQLSTATE。SQLEXCEPTION
,它是不以'00'、'01'、'02'开头的SQLSTATE
的简写。
当发生一个错误的时候,可能有多个handler可以同时处理这个错误。例如,有一个处理1050错误码的handler,一个处理SQLSTATE为42S01的handler,以及一个SQLEXCEPTION
类型的handler:在理论上,所有handler都可以捕获到1050错误,但是MariaDB将会选择优先级最高的handler进行处理。优先级规则如下:
- error code类的handler优先级最高。
- SQLSTATE类的handler优先级次之。
- 处理一整类的handler优先级最低。
某些情况下,一条语句可能会产生多个错误。如果这样,也将采用优先级最高的hanlder去处理其中一个。这种情况相下,对handler的选择可能不那么明确。
注意,如果在CONTINUE HANDLER
中发生了错误,这个错误可以被其他的HANDLER
捕获到并处理。但是,已经正在运行中的handler无法处理此时新产生的错误。例如,存储过程中包含了一个处理SQLWARNING
的CONTINUE HANDLER
以及一个处理NOT FOUND
的CONTINUE HANDLER
。当某个时刻,发生了NOT FOUND错误,于是执行NOT FOUND HANDLER
。但是这个handler中又产生了一个warning信息,于是SQLWARNING handler
将会处理这个问题。如果再次发生了一个NOT FOUND
错误,将没有handler可以处理这次的错误,因为前面的NOT FOUND HANDLER
已经正在运行。
当一个DECLARE HANDLER
语句可以处理多个错误时,可能需要有效地判断发生了什么错误。你可以使用GET DIAGNOSTICS语句来达到这样的目的。
当某个错误已被某个DECLARE HANDLER
处理后,可以使用RESIGNAL语句再次提交这个错误。
下面是DECLARE HANDLER
的一个示例:
CREATE TABLE test.t (s1 INT, PRIMARY KEY (s1)); DELIMITER // 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; // DELIMITER ; CALL handlerdemo( ); SELECT @x; +------+ | @x | +------+ | 3 | +------+