13.6.7.6 Scope Rules for Handlers处理程序的作用域规则

A stored program may include handlers to be invoked when certain conditions occur within the program. 存储程序可能包括当程序中出现某些情况时要调用的处理程序。The applicability of each handler depends on its location within the program definition and on the condition or conditions that it handles:每个处理程序的适用性取决于其在程序定义中的位置及其处理的一个或多个条件:

Multiple handlers can be declared in different scopes and with different specificities. 多个处理程序可以在不同的范围内以不同的特定性声明。For example, there might be a specific MySQL error code handler in an outer block, and a general SQLWARNING handler in an inner block. 例如,外部块中可能有一个特定的MySQL错误代码处理程序,内部块中可能有一个通用的SQLWARNING处理程序。Or there might be handlers for a specific MySQL error code and the general SQLWARNING class in the same block.或者在同一个块中可能有特定MySQL错误代码和常规SQLWARNING类的处理程序。

Whether a handler is activated depends not only on its own scope and condition value, but on what other handlers are present. 处理程序是否被激活不仅取决于其自身的作用域和条件值,还取决于存在哪些其他处理程序。When a condition occurs in a stored program, the server searches for applicable handlers in the current scope (current BEGIN ... END block). 当存储程序中出现条件时,服务器会在当前范围(当前BEGIN ... END<块)中搜索适用的处理程序。If there are no applicable handlers, the search continues outward with the handlers in each successive containing scope (block). 如果没有适用的处理程序,搜索将继续向外搜索,并在每个连续的包含范围(块)中使用处理程序。When the server finds one or more applicable handlers at a given scope, it chooses among them based on condition precedence:当服务器在给定范围内找到一个或多个适用的处理程序时,它会根据条件优先级在其中进行选择:

One implication of the handler selection rules is that if multiple applicable handlers occur in different scopes, handlers with the most local scope take precedence over handlers in outer scopes, even over those for more specific conditions.处理程序选择规则的一个含义是,如果多个适用的处理程序出现在不同的作用域中,则局部作用域最多的处理程序优先于外部作用域中的处理程序,甚至优先于更特定条件下的处理程序。

If there is no appropriate handler when a condition occurs, the action taken depends on the class of the condition:如果条件发生时没有合适的处理程序,则所采取的操作取决于条件的类别:

The following examples demonstrate how MySQL applies the handler selection rules.以下示例演示MySQL如何应用处理程序选择规则。

This procedure contains two handlers, one for the specific SQLSTATE value ('42S02') that occurs for attempts to drop a nonexistent table, and one for the general SQLEXCEPTION class:此过程包含两个处理程序,一个用于尝试删除不存在的表时出现的特定SQLSTATE值('42S02'),另一个用于常规SQLEXCEPTION类:

CREATE PROCEDURE p1()
BEGIN
  DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
    SELECT 'SQLSTATE handler was activated' AS msg;
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SELECT 'SQLEXCEPTION handler was activated' AS msg;

  DROP TABLE test.t;
END;

Both handlers are declared in the same block and have the same scope. 两个处理程序都在同一块中声明,并且具有相同的作用域。However, SQLSTATE handlers take precedence over SQLEXCEPTION handlers, so if the table t is nonexistent, the DROP TABLE statement raises a condition that activates the SQLSTATE handler:但是,SQLSTATE处理程序优先于SQLEXCEPTION处理程序,因此如果表t不存在,DROP TABLE语句将引发一个激活SQLSTATE处理程序的条件:

mysql> CALL p1();
+--------------------------------+
| msg                            |
+--------------------------------+
| SQLSTATE handler was activated |
+--------------------------------+

This procedure contains the same two handlers. 此过程包含相同的两个处理程序。But this time, the DROP TABLE statement and SQLEXCEPTION handler are in an inner block relative to the SQLSTATE handler:但这一次,DROP TABLE语句和SQLEXCEPTION处理程序位于相对于SQLSTATE处理程序的内部块中:

CREATE PROCEDURE p2()
BEGIN -- outer block
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      SELECT 'SQLSTATE handler was activated' AS msg;
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
      SELECT 'SQLEXCEPTION handler was activated' AS msg;

    DROP TABLE test.t; -- occurs within inner block
  END;
END;

In this case, the handler that is more local to where the condition occurs takes precedence. 在这种情况下,条件发生的地方更局部的处理程序优先。The SQLEXCEPTION handler activates, even though it is more general than the SQLSTATE handler:SQLEXCEPTION处理程序激活,尽管它比SQLSTATE处理程序更通用:

mysql> CALL p2();
+------------------------------------+
| msg                                |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+

In this procedure, one of the handlers is declared in a block inner to the scope of the DROP TABLE statement:在此过程中,其中一个处理程序在DROP TABLE语句范围内的块中声明:

CREATE PROCEDURE p3()
BEGIN -- outer block
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SELECT 'SQLEXCEPTION handler was activated' AS msg;
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      SELECT 'SQLSTATE handler was activated' AS msg;
  END;

  DROP TABLE test.t; -- occurs within outer block
END;

Only the SQLEXCEPTION handler applies because the other one is not in scope for the condition raised by the DROP TABLE:只有SQLEXCEPTION处理程序适用,因为另一个处理程序不在DROP TABLE引发的条件的范围内:

mysql> CALL p3();
+------------------------------------+
| msg                                |
+------------------------------------+
| SQLEXCEPTION handler was activated |
+------------------------------------+

In this procedure, both handlers are declared in a block inner to the scope of the DROP TABLE statement:在此过程中,两个处理程序都在DROP TABLE语句范围内的块中声明:

CREATE PROCEDURE p4()
BEGIN -- outer block
  BEGIN -- inner block
    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
      SELECT 'SQLEXCEPTION handler was activated' AS msg;
    DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'
      SELECT 'SQLSTATE handler was activated' AS msg;
  END;

  DROP TABLE test.t; -- occurs within outer block
END;

Neither handler applies because they are not in scope for the DROP TABLE. 这两个处理程序都不适用,因为它们不在DROP TABLE的作用域中。The condition raised by the statement goes unhandled and terminates the procedure with an error:语句引发的条件未经处理,并以错误终止过程:

mysql> CALL p4();
ERROR 1051 (42S02): Unknown table 'test.t'