7.4.3 LOOP循环控制语句
LOOP语句也叫循环语句,它能让我们重复地执行指定的语句块。LOOP语句有以下四种形式:
❑LOOP;
❑WHILE…LOOP;
❑FOR…LOOP;
❑CURSOR FOR LOOP。
本小节将介绍前三种类型,至于CURSOR FOR LOOP会在第8章中介绍。
1.基本的LOOP
该形式的语句属于LOOP循环控制语句中最基本的结构,它会重复不断地执行LOOP和END LOOP之间的语句序列。由于基本的LOOP语句本身没有包含中断循环的条件,所以通常情况下都是和其他的条件控制语句一起使用,利用EXIT、GOTO等可以中断LOOP循环。当然,异常也能使LOOP语句中断。图7.21描述了基本的LOOP语句的流程。
图 7.21 LOOP语句流程
基本的LOOP语句语法结构如下:
[<<label_name>>]
LOOP
statement…
END LOOP[label_name]
【语法说明】
❑<<label_name>>:LOOP语句的标签,是可选项。
❑LOOP:LOOP循环的开始标志。
❑statement:LOOP语句中需要重复执行的语句。
❑END LOOP:LOOP循环结束标志。
基本的LOOP语句需要和条件控制语句一起使用,否则会出现死循环的情况,直到内存溢出时抛出异常才能终止循环。通常情况下,正常终止循环的方式有以下两种:
1)在LOOP循环当中可以使用IF语句与EXIT的组合来结束循环。EXIT必须在循环体内部,它可以使循环正常无条件终止,并且终止循环后程序会正常执行循环外的语句。它如果同IF语句一起使用,表示当满足某个条件时程序退出循环体,继续向后执行。
【示例18】基本LOOP操作示例
示例简单地演示了LOOP的使用方式,要求每次循环都需要为变量增加1,并把变量输出到屏幕。当变量值大于5的时候,要求终止循环。具体脚本如下:
01 DECLARE
02 v_num NUMBER(8):=1;
03 BEGIN
04 <<basic_loop>>
05 LOOP
06 DBMS_OUTPUT.put_line('当前v_num变量的值是:'||v_num);
07 v_num:=v_num+1;
08 IF v_num>5 THEN
09 DBMS_OUTPUT.put_line('退出!当前v_num的值是'||v_num);
10 EXIT basic_loop;
11 END IF;
12 END LOOP;
13 DBMS_OUTPUT.put_line('LOOP循环已经结束!');
14 END;
15 /
【代码解析】
❑第1行为声明变量,默认值为1。
❑第4行是LOOP循环的标签,可以选择性地填写。
❑第5~12行属于一个基本的LOOP结构。
❑第7行表示每循环一次都为变量增加1。
❑第8~10行是条件语句,表示当变量v_num大于5时会退出循环。
❑第10行表示退出语句。basic_loop为LOOP的标签,这里表示的含义是退出标签名为basic_loop的循环。
【执行效果】
在SQL*Plus中执行以上脚本,查看执行结果。执行过程见图7.22。
图 7.22 LOOP中利用IF条件结束循环
EXIT默认是终止退出当前的循环,但如果使用标签,可以终止并退出指定的LOOP循环。
2)使用EXIT…WHEN语句来结束循环。这种方式在游标中会经常使用,这种情况会在后面的章节见到。它所代表的含义是:当WHEN后面的条件为TRUE时,EXIT会被触发,终止退出指定的循环,如果EXIT后不加LOOP标签,则表示终止退出当前循环。该语句可以替换简单的IF语句,下面的示例将演示这一点。
【示例19】EXIT…WHEN语句使用示例
要求使用EXIT…WHEN替换示例18中的IF语句。脚本如下:
01 DECLARE
02 v_num NUMBER(8):=1;
03 BEGIN
04 <<basic_loop>>
05 LOOP
06 DBMS_OUTPUT.put_line('当前v_num变量的值是:'||v_num);
07 v_num:=v_num+1;
08 EXIT basic_loop WHEN v_num>5;
09 END LOOP;
10
11 DBMS_OUTPUT.put_line('退出!当前v_num的值是'||v_num);
12 DBMS_OUTPUT.put_line('LOOP循环已经结束!');
13 END;
14 /
【代码解析】
❑第8行,利用EXIT…WHEN语句判断变量v_num如果大于5,则退出basic_loop循环。完成判断并退出,只需要一行脚本。
【执行效果】
在SQL*Plus中执行程序,查看结果是否与示例18相同。执行过程见图7.23。
图 7.23 LOOP中利用EXIT…WHEN语句结束循环
从图7.23的执行结果中可以看出,EXIT…WHEN语句在某些时候可以替代IF语句,而EXIT…WHEN语句更为简洁。建议读者如非必要,LOOP循环当中可以优先考虑该类型的语句。
2.WHILE…LOOP语句
WHILE…LOOP结构的语句本身可以终止LOOP循环,当WHILE后面的布尔表达式为TRUE时,LOOP和END LOOP之间的语句集将执行一次,而后会重新判断WHILE后面的表达式是否为TRUE。其流程见图7.24。
图 7.24 WHILE…LOOP流程
该语句结构的具体语法如下:
[<<label_name>>]
WHILE boolean_expression
LOOP
statement…
END LOOP[label_name];
语法中的boolean_expression项是一个布尔表达式,只有当该表达式为TRUE的时候,statement部分才能得到执行。其他部分和基本的LOOP语句没有区别。
【示例20】WHILE…LOOP语句示例
要求输出20以内能被3整除的数。脚本如下:
01 DECLARE
02 v_num NUMBER(8):=1;
03 BEGIN
04 DBMS_OUTPUT.put('当前v_num变量的值是:');
05 <<while_loop>>
06 WHILE v_num<20
07 LOOP
08 IF MOD(v_num,3)=0 THEN
09 DBMS_OUTPUT.put(v_num||'');
10 END IF;
11
12 v_num:=v_num+1;
13 END LOOP;
14
15 DBMS_OUTPUT.put_line('退出!当前v_num的值是'||v_num);
16 DBMS_OUTPUT.put_line('LOOP循环已经结束!');
17 END;
18 /
【代码解析】
❑第2行表示声明变量v_num,默认值为1。
❑第5~13行是WHILE…LOOP语句。
❑第5行是WHILE…LOOP语句的标签。
❑第6行表示当变量v_num<20时,执行下面的LOOP循环。
❑第8~10行利用SQL函数判断v_num是否能被3整除。如果整除,则把该值输出。
❑第12行表示每次循环都为变量v_num增加1。这样就可以判断1~20之间所有的数是否能被3整除。而且当变量增加到20时,循环会终止退出。
【执行效果】
在SQL*Plus中执行以上脚本,执行过程见图7.25。
图 7.25 WHILE…LOOP执行过程
这种结构模式执行的顺序是先判断后循环,所以LOOP中的语句序列有可能连一次执行的机会都没有。例如,程序中的v_num初始值若大于19,LOOP循环将得不到执行。想要避免此类情况,可以采用下列脚本的方式:
01 …
02 WHILE v_bol
03 LOOP
04 IF MOD(v_num,3)=0 THEN
05 DBMS_OUTPUT.put(v_num||'');
06 END IF;
07
08 IF v_num>=20 THEN
09 v_bol:=FALSE;
10 END IF;
11 v_num:=v_num+1;
12 END LOOP;
13 …
【代码解析】
❑第2行的v_bol是一个布尔类型的变量,默认值为TRUE类型。一旦该变量值为FALSE,循环将终止退出。
❑第8~10行判断变量v_num,如果该变量的值大于等于20,变量v_bol的值将被置为FALSE。
经过修改以后,它的执行顺序和Java语言当中的DO-WHILE语句执行顺序相同。这种方式读者应该掌握。
3.FOR…LOOP
FOR…LOOP语句循环遍历指定范围内的整数。该范围被FOR和LOOP关键词封闭。当第一次进入循环时,其循环范围会被确定,并且以后不会再次计算。每循环一次,其循环次数将会增加1。
FOR…LOOP语句的语法结构如下:
01 [<<label_name>>]
02 FOR index_name IN
03 [REVERSE]
04 lower_bound..upper_bound
05 LOOP
06 statement…
07 END LOOP[label_name];
【语法说明】
❑index_name:循环计数器,该变量可以得到当前的循环次数,但是不能为其赋值。
❑REVERSE:该项指定循环的方式。默认的循环方式是由下标界到上标界,也就是从lower_bound到upper_bound,如果使用REVERSE关键词,那么循环方式正好相反,也就是从上标界到下标界。
❑lower_bound:循环范围的下标界。
❑upper_bound:循环范围的上标界。
❑lower_bound和upper_bound两者需要用“..”连接。
【示例21】FOR…LOOP语句使用示例
该示例算出1~20之间所有整数的和。脚本如下:
01 DECLARE
02 v_num NUMBER(8):=0;
03 BEGIN
04 DBMS_OUTPUT.put('1~20之间整数和:');
05 <<for_loop>>
06 FOR inx IN 1..20 LOOP
07 v_num:=v_num+inx;
08 END LOOP;
09
10 DBMS_OUTPUT.put_line(v_num);
11 DBMS_OUTPUT.put_line('LOOP循环已经结束!');
12 END;
13 /
【代码解析】
❑第2行表示声明变量。
❑第5~8行是一个FOR…LOOP结构。
❑第6行表示循环范围从1到20。inx为循环计数器名。当inx等于20时,循环会自动退出。
❑第7行表示求出1~20之间整数的和。
【执行效果】
在SQL*Plus中执行该脚本,执行过程见图7.26。
图 7.26 FOR…LOOP语句执行过程
FOR…LOOP循环当中的循环范围可以动态地获取。例如,示例中的下标界完全可以用数值型的变量替代。
需要说明的是,当lower_bound和upper_bound相等时,循环中的语句只能执行一次。