MySQL的SQL语句 -条件处理语句(6) - 句柄的作用域规则

网友投稿 1162 2022-10-13

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

MySQL的SQL语句 -条件处理语句(6) - 句柄的作用域规则

句柄的作用域规则

存储程序可以包括程序中发生某些条件时要调用的句柄。每个句柄的适用性取决于其在程序定义中的位置及其处理的条件:

BEGIN -- outer block DECLARE EXIT HANDLER FOR ...; -- handler H1 DECLARE EXIT HANDLER FOR ...; -- handler H2 stmt1; stmt2;END;

BEGIN -- outer block BEGIN -- inner block DECLARE EXIT HANDLER FOR ...; -- handler H1 stmt1; END; stmt2;END;

● 句柄可以是特定的,也可以是常规的。特定的句柄用于 MySQL 错误代码、SQLSTATE 值或条件名称。常规句柄用于 SQLWARNING、SQLEXCEPTION 或 NOT FOUND 类中的条件。条件特征与条件优先级相关,如下文所述。

句柄是否被激活不仅取决于它自己的作用域和条件值,还取决于其他句柄的存在。当存储程序中出现条件时,服务器将在当前范围(当前 BEGIN ... END 块)搜索可用的句柄。如果没有适用的句柄,则继续向外搜索包含作用域(块)中的句柄。当服务器在给定的作用域中找到一个或多个适用的句柄时,它将根据条件优先级在其中进行选择:

● MySQL 错误代码句柄优先于 SQLSTATE 值句柄。

● SQLSTATE 值句柄优先于常规 SQLWARNING、SQLEXCEPTION 或 NOT FOUND 句柄。

● SQLEXCEPTION 句柄优先于 SQLWARNING 句柄。

● 可以有几个具有相同优先级的适用句柄。例如,一条语句可以生成多个带有不同错误代码的警告,其中每个都有特定于错误的句柄。在这种情况下,服务器激活哪个句柄的选择是不确定的,并且可能会根据条件发生的环境而改变。

句柄选择规则的一个含义是,如果多个适用的句柄出现在不同的作用域中,则具有最局部作用域的句柄优先于外部作用域中的句柄,甚至优先于更明确条件下的句柄。

如果条件发生时没有适当的句柄,则所采取的操作取决于条件的类:

● 对于 SQLEXCEPTION 条件,存储程序在引发该条件的语句处终止,就好像存在一个 EXIT 句柄一样。如果程序被另一个存储程序调用,则调用程序将使用应用于自己的句柄的句柄选择规则来处理该条件。

● 对于 SQLWARNING 条件,程序将继续执行,就像有一个 CONTINUE 句柄一样。

● 对于 NOT FOUND 条件,如果条件正常引发,则操作为 CONTINUE。如果是通过 SIGNAL 或 RESIGNAL 引发的,则操作是 EXIT。

下面的示例演示 MySQL 如何应用句柄选择规则。

此过程包含两个句柄,一个用于尝试删除不存在的表时发生的特定 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;

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

此过程包含相同的两个句柄。但这一次,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;

在这种情况下,对条件发生的位置更为局部的句柄优先。SQLEXCEPTION 句柄激活,尽管它比 SQLSTATE 句柄更通用:

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

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 blockEND;

只有 SQLEXCEPTION 句柄适用,因为另一个句柄不在 DROP TABLE 引发的条件的作用域内:

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

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 blockEND;

这两个句柄都不适用,因为它们不在 DROP TABLE 的作用域中。语句引发的条件未经处理,并以错误终止过程:

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

官方网址:

https://dev.mysql.com/doc/refman/8.0/en/handler-scope.html

上一篇:写给运维兄弟
下一篇:kubernetes夺命十三连问
相关文章

 发表评论

暂时没有评论,来抢沙发吧~