ITPub博客

首页 > 数据库 > > 13.6 复合语句语法

13.6 复合语句语法

作者:飘絮絮絮丶 时间:2020-05-12 10:21:28 0 删除 编辑

参考官方文档:

dev.mysql.com/doc/refma


本节介绍BEGIN ... END复合语句的语法以及可用于存储程序主体的其他语句:存储过程和函数,触发器和事件。 这些对象是根据存储在服务器上供以后调用的SQL代码定义的(请参见第23章,存储程序和视图)。


复合语句是一个可以包含其他块的块; 变量声明,条件处理程序和游标; 和流程控制结构,如循环和条件测试。


13.6.1 BEGIN .... END 复合语句语法


[begin_label:]

BEGIN

[statement_list]

END [end_label]


BEGIN ... END语法用于编写复合语句,它可以出现在存储程序(存储过程和函数,触发器和事件)中。 复合语句可以包含多个由BEGIN和END关键字包围的语句。 statement_list表示一个或多个语句的列表,每个语句以分号(;)语句分隔符结尾。 statement_list本身是可选的,所以空的复合语句(BEGIN END)是合法的。


BEGIN ... END 块 可以被嵌套。

使用多个语句要求客户端能够发送包含该语句的语句字符串; 语句分隔符。 在mysql命令行客户端中,这是通过delimiter命令处理的。 改变; 语句结尾分隔符(例如,//)允许; 号用于程序主体。


不支持可选的[NOT] ATOMIC子句。 这意味着在指令块的开始处没有设置事务性保存点,并且在此上下文中使用的BEGIN子句对当前事务没有影响。


注意:

在所有存储的程序中,解析器将BEGIN [WORK]视为BEGIN ... END块的开始。 要在此上下文中开始事务,请改用START TRANSACTION。





13.6.2 Label 语句语法


[begin_label:] BEGIN

[statement_list]

END [end_label]


[begin_label:] LOOP

statement_list

END LOOP [end_label]


[begin_label:] REPEAT statement_list

UNTIL search_condition END REPEAT [end_label]


[begin_label:] WHILE search_condition DO

statement_list

END WHILE [end_label]


BEGIN ... END块以及LOOP,REPEAT和WHILE语句允许使用标签。 这些语句的标签使用遵循以下规则:


  • begin_label 必须被跟随一个冒号:
  • begin_label可以在没有end_label的情况下给出。 如果end_label存在,它必须与begin_label相同。
  • 没有begin_label就无法给出end_label。
  • 相同嵌套级别的标签必须是不同的。
  • 标签最长可以有16个字符。


要在标签结构中引用标签,请使用ITERATE或LEAVE语句。 以下示例使用这些语句继续迭代或终止循环:


CREATE PROCEDURE doiterate(p1 INT)

BEGIN

label1: LOOP SET

p1 = p1 + 1;

IF p1 < 10 THEN ITERATE label1;

END IF;

LEAVE label1;

END LOOP label1;

END;

块标签的范围不包括块内声明的处理程序的代码。

13.6.3 DECLARE 语法

DECLARE语句用于定义程序本地的各种项目:

  • 本地变量
  • 条件和处理
  • 游标


只有在BEGIN ... END复合语句中才允许DECLARE,并且必须处于在任何其他语句开始之前。

声明必须遵循特定的顺序。 游标声明必须出现在处理程序声明之前。 变量和条件声明必须出现在游标或处理程序声明之前。

13.6.4 在存储过程中的变量


系统变量和用户定义的变量可以在存储程序中使用,就像它们可以在存储程序上下文中使用一样。 另外,存储的程序可以使用DECLARE来定义局部变量,并且可以声明存储的例程(过程和函数)以获取在例程与其调用者之间传递值的参数。

  • 要声明本地变量,使用 DECLARE 语句。
  • 变量可以用SET语句直接设置。
  • 可以使用SELECT ... INTO var_list或通过打开游标并使用FETCH ... INTO var_list将查询结果检索到局部变量中。


不允许将值DEFAULT分配给存储过程或函数参数或存储的程序局部变量(例如,使用SET var_name = DEFAULT语句)。 在MySQL 5.7中,这会导致语法错误。


13.6.4.1 本地变量 DECLARE 语法


DECLARE var_name [, var_name] ... type [DEFAULT value]

该语句在存储的程序中声明局部变量。 要为变量提供默认值,请包含DEFAULT子句。 该值可以被指定为一个表达式; 它不一定是常数。 如果缺少DEFAULT子句,则初始值为NULL。

就数据类型和溢出检查而言,局部变量被视为存储的例程参数

变量声明必须出现在游标或处理程序声明之前。

局部变量名称不区分大小写。 允许的字符和引用规则与其他标识符相同,如第9.2节“模式对象名称”中所述。

局部变量的作用域是声明它的BEGIN ... END块。 变量可以在嵌套在声明块中的块中引用,除了声明了具有相同名称的变量的块之外(内部变量覆盖外部局部变量)。


13.6.4.2 局部变量范围和解决方案


局部变量的作用域是声明它的BEGIN ... END块。 变量可以在嵌套在声明块中引用,除了声明具有相同名称的变量的块之外。

因为局部变量仅在存储程序执行期间处于作用域中,所以在存储程序中创建的预处理语句中不允许对它们进行引用。 准备好的语句范围是当前会话,而不是存储的程序,因此语句可以在程序结束后执行,此时变量将不再处于范围内。 例如,SELECT ... INTO local_var不能用作预准备语句。 这个限制也适用于存储过程和函数参数。


一个局部变量不应该与表列具有相同的名称。 如果一个SQL语句(如SELECT ... INTO语句)包含对同名的列和声明局部变量的引用,那么MySQL当前将该引用解释为变量的名称。 考虑下面的过程定义:


CREATE PROCEDURE sp1 (x VARCHAR(5))

BEGIN DECLARE xname VARCHAR(5) DEFAULT 'bob';

DECLARE newname VARCHAR(5);

DECLARE xid INT;

SELECT xname, id INTO newname, xid FROM table1

WHERE xname = xname;

SELECT newname;

END;


MySQL将SELECT语句中的xname解释为对xname变量的引用,而不是xname列。 因此,在调用过程sp1()时,无论table1.xname列的值如何,newname变量都会返回值“bob”。

同样,以下过程中的游标定义包含引用xname的SELECT语句。 MySQL将其解释为对该名称的变量的引用,而不是列引用。


CREATE PROCEDURE sp2 (x VARCHAR(5))

BEGIN DECLARE xname VARCHAR(5) DEFAULT 'bob';

DECLARE newname VARCHAR(5);

DECLARE xid INT;

DECLARE done TINYINT DEFAULT 0;

DECLARE cur1 CURSOR FOR SELECT xname, id FROM table1;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN cur1; read_loop: LOOP

FETCH FROM cur1 INTO newname, xid;

IF done THEN LEAVE read_loop;

END IF;

SELECT newname;

END LOOP;

CLOSE cur1;

END;


13.6.5 流控制语句

MySQL支持用于存储程序中流量控制的IF,CASE,ITERATE,LEAVE LOOP,WHILE和REPEAT结构。 它还支持存储函数中的RETURN。

这些结构中的很多都包含其他语句,如以下各节中的语法规范所示。 这样的构造可以嵌套。 例如,一个IF语句可能包含一个WHILE循环,它本身包含一个CASE语句。

MySQL不支持FOR循环。


13.6.5.1 CASE 语法

CASE case_value

WHEN when_value THEN statement_list

[WHEN when_value THEN statement_list]

...

[ELSE statement_list]

END CASE


CASE

WHEN search_condition

THEN statement_list

[WHEN search_condition THEN statement_list]

... [ELSE statement_list]

END CASE


存储程序的CASE语句实现了一个复杂的条件构造。

注意:

还有一个CASE表达式,它不同于这里描述的CASE语句。 参见第12.4节“控制流量功能”。 CASE语句不能有ELSE NULL子句,并且它以END CASE而不是END结束。


对于第一种语法,case_value是一个表达式。 将该值与每个WHEN子句中的when_value表达式进行比较,直到其中一个相等。 如果找到相等的when_value,则执行相应的THEN子句statement_list。 如果没有when_value相等,则执行ELSE子句statement_list(如果有)。

此语法不能用于测试与NULL的相等性,因为NULL = NULL为假。


对于第二种语法,每个WHEN子句的search_condition表达式将被计算,直到其中一个为真,此时其相应的THEN子句statement_list将执行。 如果没有search_condition为真,则执行ELSE子句statement_list(如果有)。


如果没有when_value或search_condition与测试值相匹配,并且CASE语句不包含ELSE子句,则出现错误 Case not found for CASE statement。

每个statement_list由一个或多个SQL语句组成; 一个空的statement_list是不允许的。


要处理没有任何WHEN子句匹配任何值的情况,请使用包含空BEGIN ... END块的ELSE,如本例所示。


DELIMITER |

CREATE PROCEDURE p()

BEGIN DECLARE v INT DEFAULT 1;

CASE v

WHEN 2 THEN SELECT v;

WHEN 3 THEN SELECT 0;

ELSE

BEGIN

END;

END CASE;

END;

|


13.6.5.2 IF 语法

IF search_condition THEN statement_list

[ELSEIF search_condition THEN statement_list] ...

[ELSE statement_list]

END IF


存储程序的IF语句实现了一个基本的条件构造。

注意:

还有一个IF()函数,它不同于这里描述的IF语句。 IF语句可以有THEN,ELSE和ELSEIF子句,并以END IF结束


如果search_condition的计算结果为true,则执行相应的THEN或ELSEIF子句statement_list。 如果没有search_condition匹配,则执行ELSE子句statement_list。

每个statement_list由一个或多个SQL语句组成; 一个空的statement_list是不允许的。


IF ... END IF块与存储程序中使用的所有其他流控块一样,必须以分号结尾,如下例所示:


DELIMITER //

CREATE FUNCTION SimpleCompare(n INT, m INT) RETURNS VARCHAR(20) BEGIN DECLARE s VARCHAR(20);

IF n > m THEN SET s = '>';

ELSEIF n = m THEN SET s = '=';

ELSE SET s = '<';

END IF;

SET s = CONCAT(n, ' ', s, ' ', m);

RETURN s;

END //

DELIMITER ;

与其他流程控制结构一样,IF ... END IF块可嵌套在其他流程控制结构中,包括其他IF语句。 每个IF必须以自己的END IF结尾,后跟分号。 您可以使用缩进来使嵌套流控块更容易被人读取(尽管这不是MySQL所要求的),如下所示:


DELIMITER //

CREATE FUNCTION VerboseCompare (n INT, m INT) RETURNS VARCHAR(50) BEGIN

DECLARE s VARCHAR(50);

IF n = m THEN SET s = 'equals';

ELSE

IF n > m THEN SET s = 'greater';

ELSE SET s = 'less';

END IF;

SET s = CONCAT('is ', s, ' than');

END IF;

SET s = CONCAT(n, ' ', s, ' ', m, '.');

RETURN s;

END //

DELIMITER ;

在这个例子中,只有在n不等于m时才评估内部IF。


13.6.5.3 ITERATE 语法

ITERATE label


ITERATE只能出现在LOOP,REPEAT和WHILE语句中。 ITERATE的意思是“再次启动循环”。

13.6.5.4 LEAVE 语法

LEAVE label

此语句用于退出具有给定标签的流控制结构。 如果标签用于最外面存储的程序块,则LEAVE退出程序。

LEAVE可以在BEGIN ... END或循环结构(LOOP,REPEAT,WHILE)中使用。


13.6.5.5 LOOP 语法

[begin_label:] LOOP

statement_list

END LOOP [end_label]

LOOP实现了一个简单的循环结构,可以重复执行语句列表,它由一个或多个语句组成,每个语句由一个分号(;)语句分隔符终止。 重复循环内的语句,直到循环结束。 通常,这是通过LEAVE语句完成的。 在存储的函数中,也可以使用RETURN,它完全退出函数。

忽略包含循环终止语句会导致无限循环。

例子:


CREATE PROCEDURE doiterate(p1 INT)

BEGIN

label1: LOOP

SET p1 = p1 + 1;

IF p1 < 10 THEN

ITERATE label1;

END IF;

LEAVE label1;

END LOOP label1;

SET @x = p1;

END;

13.6.5.6 REPEAT 语句


[begin_label:] REPEAT

statement_list

UNTIL search_condition

END REPEAT [end_label]


重复REPEAT语句中的语句列表,直到search_condition表达式为真。 因此,REPEAT总是至少进入一次循环。 statement_list由一个或多个语句组成,每个语句由分号(;)语句分隔符终止。

REPEAT语句可以被标记。

例子:

mysql> delimiter //

mysql> CREATE PROCEDURE dorepeat(p1 INT)

-> BEGIN

-> SET @x = 0;

-> REPEAT

-> SET @x = @x + 1;

-> UNTIL @x > p1 END REPEAT;

-> END

-> // Query OK, 0 rows affected (0.00 sec)

mysql> CALL dorepeat(1000)// Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @x//

+------+

| @x |

+------+

| 1001 |

+------+

1 row in set (0.00 sec)


13.6.5.7 RETURN 语法

RETURN expr

RETURN语句终止存储函数的执行并将值expr返回给函数调用者。 存储函数中必须至少有一个RETURN语句。 如果函数有多个出口点,可能会有多个。

此语句不用于存储过程,触发器或事件。 LEAVE语句可用于退出这些类型的存储程序。


13.6.5.8 WHILE 语法


[begin_label:] WHILE search_condition DO

statement_list

END WHILE [end_label]


只要search_condition表达式为真,WHILE语句中的语句列表就会重复。 statement_list由一个或多个SQL语句组成,每个SQL语句以分号(;)语句分隔符结尾。


WHILE语句可以被标记。


例子:

CREATE PROCEDURE dowhile()

BEGIN

DECLARE v1 INT DEFAULT 5;

WHILE v1 > 0 DO

...

SET v1 = v1 - 1;

END WHILE;

END;


13.6.6 游标


MySQL支持存储程序中的游标。 语法与嵌入式SQL中的一样。 游标具有以下属性:


  • 敏感性:服务器可能会或不会产生其结果表的副本
  • 只读性:不可更新
  • 不可滚动:只能在一个方向上移动,不能跳过行

游标声明必须出现在处理程序声明之前以及变量和条件声明之后。


例子:

CREATE PROCEDURE curdemo()

BEGIN DECLARE done INT DEFAULT FALSE;

DECLARE a CHAR(16);

DECLARE b, c INT;

DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;

DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;


OPEN cur1;

OPEN cur2;

read_loop: LOOP

FETCH cur1 INTO a, b;

FETCH cur2 INTO c;

IF done THEN

LEAVE read_loop;

END IF;

IF b < c THEN

INSERT INTO test.t3 VALUES (a,b);

ELSE

INSERT INTO test.t3 VALUES (a,c);

END IF;

END LOOP;

CLOSE cur1;

CLOSE cur2;

END;

13.6.6.1 cursor CLOSE 语法


CLOSE cursor_name

该语句关闭以前打开的光标。

如果光标未打开,则会发生错误。


如果未明确关闭,则会在声明它的BEGIN ... END块的末尾关闭游标。


13.6.6.2 游标 DECLARE 语法

DECLARE cursor_name CURSOR FOR select_statement


该语句声明一个游标并将其与一个SELECT语句相关联,该语句检索要由游标遍历行。 要稍后获取行,请使用FETCH语句。 SELECT语句检索的列数必须与FETCH语句中指定的输出变量数相匹配。

SELECT语句不能有INTO子句。

游标声明必须出现在处理程序声明之前以及变量和条件声明之后。

存储的程序可能包含多个游标声明,但在给定块中声明的每个游标必须具有唯一的名称。

有关通过SHOW语句获得的信息,在很多情况下可以通过使用具有INFORMATION_SCHEMA表的来获得游标等效信息。


13.6.6.3 Cursor FETCH 语句

FETCH [[NEXT] FROM] cursor_name INTO var_name [, var_name] ...

该语句为与指定游标(必须打开)关联的SELECT语句提取下一行,并推进游标指针。 如果存在一行,则提取的列将存储在命名变量中。 SELECT语句检索的列数必须与FETCH语句中指定的输出变量数相匹配。


如果没有更多行可用,则SQLSTATE值为'02000'时会发生无数据条件。 为了检测这种情况,你可以为它设置一个处理程序(或者对于NOT FOUND条件)。


请注意,另一个操作(如SELECT或另一个FETCH)也可能会导致处理程序通过抛出相同条件来执行。 如果有必要区分哪种操作引发了这种情况,请将操作放在其自己的BEGIN ... END块中,以便它可以与自己的处理程序关联。



13.6.6.4 游标OPEN 语法

OPEN cursor_name

这个语句打开一个先前声明的游标。


13.6.7 条件处理


存储程序执行期间可能会出现需要特殊处理的条件,例如退出当前程序块或继续执行。 处理程序可以定义为一般条件,如警告或异常,或针对特定条件(如特定的错误代码)。 特定的条件可以分配名称并在相关的处理程序中以特有方式处理。


要命名一个条件,请使用DECLARE ... CONDITION语句。 要声明处理程序,请使用DECLARE ... HANDLER语句。


要从诊断区域检索信息,请使用GET DIAGNOSTICS语句(请参见第13.6.7.3节“GET DIAGNOSTICS Syntax”)。

13.6.7.1 DECLARE ... CONDITION 语法


DECLARE condition_name CONDITION FOR


condition_value condition_value:

mysql_error_code | SQLSTATE [VALUE] sqlstate_value


DECLARE ... CONDITION语句声明了一个命名错误条件,将名称与需要特定处理的条件相关联。 该名称可以在随后的DECLARE ... HANDLER语句中引用(请参见第13.6.7.2节“DECLARE ... HANDLER语法”)。


条件声明必须出现在游标或处理程序声明之前。

DECLARE ... CONDITION的condition_value指示与条件名称关联的特定条件或条件类别。 它可以采取以下形式:

  • mysql_error_code:表示MySQL错误代码的整数文字。

不要使用MySQL错误代码0,因为它表示成功,而不是错误条件。 有关MySQL错误代码的列表,请参见第B.3节“服务器错误代码和消息”。

  • SQLSTATE [VALUE] sqlstate_value:表示SQLSTATE值的5个字符的字符串文字

不要使用以'00'开头的SQLSTATE值,因为这些值指示成功而不是错误条件。 有关SQLSTATE值的列表,请参见第B.3节“服务器错误代码和消息”。

在SIGNAL或使用RESIGNAL语句中引用的条件名称必须与SQLSTATE值关联,而不是MySQL错误代码。

使用条件名称可以帮助使存储的程序代码更加清晰。 例如,此处理程序适用于尝试删除不存在的表,但只有在您知道1051是“未知表”的MySQL错误代码时才会显示该处理程序:


DECLARE CONTINUE HANDLER FOR 1051

BEGIN

-- body of handler

END;


通过为条件声明一个名称,更容易看到处理程序的目的:

DECLARE no_such_table CONDITION FOR 1051;

DECLARE CONTINUE HANDLER FOR no_such_table

BEGIN

-- body of handler

END;


以下是针对相同条件的命名条件,但是基于相应的SQLSTATE值而不是MySQL错误代码:

DECLARE no_such_table CONDITION FOR SQLSTATE '42S02';

DECLARE CONTINUE HANDLER FOR no_such_table

BEGIN

-- body of handler

END;



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

DECLARE ... HANDLER语句指定处理一个或多个条件的处理程序。 如果出现这些情况之一,则执行指定的语句。 语句可以是一个简单的语句,如SET var_name = value或使用BEGIN和END写入的复合语句。


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


handler_action值指示处理程序语句执行后处理程序执行的操作:

  • CONTINUE:继续执行当前程序。
  • EXIT:执行终止于声明处理程序的BEGIN ... END复合语句。 即使条件出现在内部块中也是如此。
  • UNDO:不支持。

DECLARE ... HANDLER的condition_value指示激活处理程序的特定条件或条件类。 它可以采取以下形式:

  • mysql_error_code:表示MySQL错误代码的整数字面值,如1051指定“未知表”:

DECLARE CONTINUE HANDLER FOR 1051

BEGIN -- body of handler

END;

不要使用MySQL错误代码0,因为它表示成功,而不是错误条件。

  • SQLSTATE [VALUE] sqlstate_value:表示SQLSTATE值的5个字符的字符串文字,例如'42S01'以指定“未知表格”:

DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02'

BEGIN

-- body of handler

END;


不要使用以'00'开头的SQLSTATE值,因为这些值指示成功而不是错误条件。

  • condition_name:先前用DECLARE ... CONDITION指定的条件名称。 条件名称可以与MySQL错误代码或SQLSTATE值关联。
  • SQLWARNING:以'01'开头的SQLSTATE类的简写。

DECLARE CONTINUE HANDLER FOR SQLWARNING

BEGIN

-- body of handler

END;

  • NOT FOUND:

以'02'开头的SQLSTATE类的简写。 这在游标的上下文中是相关的,用于控制当游标到达数据集的末尾时发生的情况。 如果没有更多行可用,则SQLSTATE值为'02000'时会发生无数据条件。 为了检测这种情况,你可以为它设置一个处理程序或者为一个NOT FOUND条件。

DECLARE CONTINUE HANDLER FOR NOT FOUND

BEGIN

-- body of handler

END;

对于SELECT ... INTO不检索行的var_list语句也会发生NOT FOUND条件。

  • SQLEXCEPTION:

对于不以'00','01'或'02'开头的SQLSTATE类的简写。

DECLARE CONTINUE HANDLER FOR SQLEXCEPTION

BEGIN

-- body of handler

END;

如果发生没有声明处理程序的情况,则采取的操作取决于条件类:

  • 对于SQLEXCEPTION条件,存储的程序在引发该条件的语句处终止,就像存在EXIT处理程序一样。 如果程序被另一个存储的程序调用,调用程序将使用应用于其自身处理程序的处理程序选择规则处理条件。
  • 对于SQLWARNING条件,程序继续执行,就像有一个CONTINUE处理程序一样。
  • 对于NOT FOUND条件,如果条件被正常抛出,则操作为CONTINUE。 如果它是由SIGNAL或RESIGNAL抛出的,则该操作为EXIT。


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

注意@x在执行该过程后为3,这表示在错误发生后继续执行过程的结束。 如果DECLARE ... HANDLER语句不存在,则由于PRIMARY KEY约束,MySQL在第二次INSERT失败后会采取默认操作(EXIT),并且SELECT @x将返回2。


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

DECLARE CONTINUE HANDLER FOR SQLWARNING BEGIN END;

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

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

  • 要跳出块,使用EXIT处理程序。 如果不需要块清理,则BEGIN ... END处理程序主体可以为空:


DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END;

否则,将清理语句放在处理程序体中:

DECLARE EXIT HANDLER FOR SQLWARNING

BEGIN

block cleanup statements

END;

要继续执行,请在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; U

NTIL FALSE END REPEAT;

END;

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3159316/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: 9.1 Literal Values
请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42570