DECLARE HANDLER

You are viewing an old version of this article. View the current version here.

语法

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无法处理此时新产生的错误。例如,存储过程中包含了一个处理SQLWARNINGCONTINUE HANDLER以及一个处理NOT FOUNDCONTINUE 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 |
+------+

Comments

Comments loading...
Content reproduced on this site is the property of its respective owners, and this content is not reviewed in advance by MariaDB. The views, information and opinions expressed by this content do not necessarily represent those of MariaDB or any other party.