流程控制语句
MySQL的支持IF
,CASE
,ITERATE
,LEAVE,
LOOP
WHILE
REPEAT
RETURN
,和用于存储程序中流程控制结构。它还支持内部存储功能。
如以下各节中的语法规范所示,这些构造中的许多构造还包含其他语句。这样的构造可以是嵌套的。例如,一条IF
语句可能包含一个WHILE
循环,而该循环本身包含一条CASE
语句。
MySQL不支持FOR
循环。
CASE语句
CASE case_valueWHEN when_valueTHEN statement_list [WHEN when_valueTHEN statement_list] ... [ELSE statement_list]END CASE
要么:
CASEWHEN search_conditionTHEN statement_list [WHEN search_conditionTHEN statement_list] ... [ELSE statement_list]END CASE
CASE
存储程序的语句实现了复杂的条件构造。
注意还有一个expr,与这里描述的语句不同。该语句不能有子句,并且以代替。
CASE
CASE
CASE
ELSE NULL
END CASE
END
对于第一种语法,case_value
是一个表达式。将该值与when_value
每个WHEN
子句中的表达式进行比较,直到其中一个相等为止。when_value
找到相等时,将执行相应的THEN
子句statement_list
。如果不when_value
等于,则执行ELSE
子句statement_list
(如果存在)。
NULL
由于NULL = NULL
为false ,因此无法使用此语法测试是否相等。请参见“使用空值”。
对于第二种语法,将评估每个WHEN
子句search_condition
表达式,直到一个为真为止,然后执行其对应的THEN
子句statement_list
。如果不search_condition
等于,则执行ELSE
子句statement_list
(如果存在)。
如果否when_value
或search_condition
与测试的值匹配,并且该CASE
语句不包含任何ELSE
子句,则导致CASE语句错误找不到Case。
每个都statement_list
包含一个或多个SQL语句;statement_list
不允许为空。
要处理任何WHEN
子句都没有值匹配的情况,请使用ELSE
包含一个空BEGIN ... END
块的,如本示例所示。(本节中此处使用的缩进ELSE
仅是为了清楚起见,在其他方面并不重要。)
DELIMITER |CREATE PROCEDURE p()BEGIN DECLARE v INTDEFAULT 1; CASE vWHEN 2THEN SELECT v;WHEN 3THEN SELECT 0;ELSE BEGIN END ;END CASE;END ; |
IF语句
IF search_conditionTHEN statement_list [ELSEIF search_conditionTHEN statement_list] ... [ELSE statement_list]END IF
IF
存储程序的语句实现了基本的条件构造。
注意还有一个函数,与此处描述的语句不同。该语句可以具有,和子句,并以终止。
IF()
IF
IF
THEN
ELSE
ELSEIF
END IF
如果给定的结果search_condition
为true,则执行相应的THEN
or 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 > mTHEN SET s = '>';ELSEIF n = mTHEN 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 = mTHEN SET s = 'equals';ELSE IF n > mTHEN 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 ;
在此示例中,IF
仅当n
不等于时才评估内部m
。
ITERATE语句
ITERATE label
ITERATE
只能出现LOOP
,REPEAT
和WHILE
语句。ITERATE
表示“再次开始循环。”
LEAVE声明
LEAVE label
该语句用于退出具有给定标签的流控制构造。如果标签用于最外层存储的程序块,则LEAVE
退出程序。
LEAVE
可以内使用BEGIN ... END
或循环结构(LOOP
,REPEAT
,WHILE
)。
LOOP声明
[begin_label:]LOOP statement_listEND LOOP [end_label]
LOOP
实现了一个简单的循环结构,使语句列表可以重复执行,该语句列表由一个或多个语句组成,每个;
语句均以分号()语句定界符终止。重复循环中的语句,直到循环终止。通常,这是通过LEAVE
声明来完成的。在已存储的函数内,RETURN
也可以使用它完全退出该函数。
忽略包含循环终止语句会导致无限循环。
LOOP
可以标记一个声明。有关标签使用的规则,请参见“SIGNAL语句”。
例:
CREATE PROCEDURE doiterate(p1 INT)BEGIN label1:LOOP SET p1 = p1 + 1;IF p1 < 10THEN ITERATE label1;END IF ;LEAVE label1;END LOOP label1;SET @x = p1;END ;
REPEAT语句
[begin_label:]REPEAT statement_listUNTIL search_conditionEND REPEAT [end_label]
REPEAT
重复语句中的语句列表,直到search_condition
表达式为真为止。因此,a REPEAT
总是至少进入一次循环。statement_list
由一个或多个语句组成,每个语句以分号(;
)语句定界符终止。
REPEAT
可以标记一个声明。有关标签使用的规则,请参见“SIGNAL语句”。
例:
mysql>delimiter // mysql>CREATE PROCEDURE dorepeat(p1 INT)BEGIN SET @x = 0;REPEAT SET @x = @x + 1;UNTIL @x > p1END 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)
RETURN语句
RETURN expr
该RETURN
语句终止存储函数的执行,并将该值返回expr
给函数调用者。RETURN
存储的函数中必须至少有一个语句。如果函数具有多个退出点,则可能有多个。
在存储过程,触发器或事件中不使用该语句。该LEAVE
语句可用于退出那些类型的存储程序。
WHILE陈述式
[begin_label:]WHILE search_conditionDO statement_listEND WHILE [end_label]
WHILE
只要search_condition
表达式为真,就会重复语句中的语句列表。statement_list
由一个或多个SQL语句组成,每个语句以分号(;
)语句定界符终止。
WHILE
可以标记一个声明。有关标签使用的规则,请参见“SIGNAL语句”。
例:
CREATE PROCEDURE dowhile()BEGIN DECLARE v1 INTDEFAULT 5;WHILE v1 > 0DO ...SET v1 = v1 - 1;END WHILE ;END ;