13.6.7.2 DECLARE ... HANDLER 语句

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
}

声明...处理程序语句指定处理一个或多个条件的处理程序。如果出现这些情况之一,则执行指定的* statement *。 * statement *可以是简单的语句,例如SET var_name = value,也可以是使用BEGINEND编写的复合语句(请参见第 13.6.1 节“ BEGIN ... END 复合语句”)。

处理程序声明必须出现在变量或条件声明之后。

声明...处理程序的* condition_value *table 示激活处理程序的特定条件或条件类别。它可以采用以下形式:

DECLARE CONTINUE HANDLER FOR 1051
  BEGIN
    -- body of handler
  END;

不要使用 MySQL 错误代码 0,因为这 table 示成功而不是错误情况。有关 MySQL 错误代码的列 table,请参见第 B.3.1 节“服务器错误消息参考”

DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
  BEGIN
    -- body of handler
  END;

不要使用以'00'开头的 SQLSTATE 值,因为这些值 table 示成功而不是错误情况。有关 SQLSTATE 值的列 table,请参见第 B.3.1 节“服务器错误消息参考”

DECLARE CONTINUE HANDLER FOR SQLWARNING
  BEGIN
    -- body of handler
  END;
DECLARE CONTINUE HANDLER FOR NOT FOUND
  BEGIN
    -- body of handler
  END;

有关另一个示例,请参见第 13.6.6 节“游标”。对于不检索任何行的SELECT ... INTO var_list语句,也会发生NOT FOUND条件。

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
  BEGIN
    -- body of handler
  END;

有关在条件发生时服务器如何选择处理程序的信息,请参见第 13.6.7.6 节“处理程序的范围规则”

如果发生未声明任何处理程序的条件,则采取的操作取决于条件类:

以下示例对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)

请注意,过程执行后@x3,这 table 明在错误发生之后,执行将 continue 到过程结束。如果不存在声明...处理程序语句,则在第二个INSERT由于PRIMARY KEY约束而失败后,MySQL 将采取默认操作(EXIT),并且SELECT @x将返回2

要忽略条件,请为其声明CONTINUE处理程序并将其与空块关联。例如:

DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;

块标签的范围不包括在块内声明的处理程序的代码。因此,与处理程序关联的语句不能使用ITERATELEAVE来引用包含处理程序声明的块的标签。考虑下面的示例,其中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

为避免在处理程序中引用外部标签,请使用以下策略之一:

DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END;

否则,将清除语句放入处理程序主体中:

DECLARE EXIT HANDLER FOR SQLWARNING
  BEGIN
    block cleanup statements
  END;
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;
首页