Skip to content

17.7 错误状况及处理

在存储程序执行的时候可能会发生错误的状况CONDITION,并要求特殊的处理。可以为通常的状况例如警告或异常,或者特殊的状况例如特殊的错误码定义处理器HANDLER。可以为特定状况指定名称并在处理器中以这种方式引用。

在MySQL5.6.3版本之前,如果语句生成的警告或错误引起了状况处理器的调用,处理器可能不会清理掉诊断区域,这会导致处理器看起来没有被调用一样。解决办法是在让处理器执行一条无意义的语句来覆盖诊断区域。

1. 状况

DECLARE condition_name CONDITION FOR condition_value

condition_value:
    mysql_error_code
  | SQLSTATE [VALUE] sqlstate_value

该语句声明了一个错误的状况,绑定了一个名字用于特定的处理(可用于处理器的声明语句)。

  • 该语句必须在CURSORHANDLER语句之前声明。
  • mysql_error_code:一个表明MySQL错误码的整数值
  • sqlstate_value:表明SQLSTATE值的5个字符的字符串
  • 状态码condition_value不能指定为0或以'00'开头,这些是表示正确地状态码。5.5错误码手册
-- mysql_error_code格式
DECLARE no_such_table CONDITION FOR 1051;
DECLARE CONTINUE HANDLER FOR no_such_table
  BEGIN
    -- body of handler
  END;

-- SQLSTATE sqlstate_value格式
DECLARE no_such_table CONDITION FOR SQLSTATE '42S02';
DECLARE CONTINUE HANDLER FOR no_such_table
  BEGIN
    -- body of handler
  END;

2. 处理器

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
    -- 发生状况时执行的语句
    -- 可以是简单的语句或是使用`BEGIN...END`编写的复合语句

指定一个处理器来处理一种或多种状况。

  • handler_action表明在执行完statement之后采取什么动作:
    • CONTINUE:继续执行当前程序
    • EXIT:终止执行处理器声明所在的BEGIN...END复合语句
    • UNDO:不支持???
  • condition_value表明触发的状况
    • mysql_error_code:表示MySQL的错误码,整型
    • SQLSTATE [VALUE] sqlstate_value:5个字符长度的SQLSTATE 值
    • condition_name:声明的状况名字
    • SQLWARNING:SQLSTATE以“01”开头的值的简写
    • NOT FOUND:SQLSTATE以“02”开头的值的简写
    • SQLEXCEPTION:SQLSTATE不以“00、01、02”开头的值的简写

注意事项

  • 处理器必须在变量和状况之后声明。
  • 如果存储过程因为一个未处理的异常而退出,修改过的OUTINOUT参数的值不会返回给调用者。
  • 如果一个异常被包含了RESIGNAL语句的CONTINUEEXIT类型的处理器处理了,RESIGNAL的执行会发出异常信号???。如果异常是一个错误,OUTINOUT参数的值不会返回给调用者。
  • 代码块的标签的作用域不包括处理器的执行语句,所以处理器的执行语句中不能包含标签(label)。避免使用外部标签的方法:
    • 需要离开代码块时,使用EXIT类型的处理器。
    • 需要继续执行时,在CONTINUE类型的处理器中设置一个可以被检测到的状态变量来指示处理器是否被调用了。例:
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;

2.1 不指定处理器时

如果没有为一种状况指定处理器,那么发生的动作取决于状况的类型:

  • NOT FOUND:如果是正常抛出的,动作是CONTINUE;如果被SIGNALRESIGNAL抛出的,动作是EXIT
  • SQLWARNING:程序继续执行,就好像存在一个CONTINUE类型的处理器
  • SQLEXCEPTION:存储程序在引发状况的语句终止,就好像存在一个EXIT类型的处理器。如果这个程序被另一个存储程序调用,调用的程序会按自己的处理器选择规则应用到自身的处理器。