
2.6.2 循环语句
DM SQL程序支持4种基本类型的循环语句,即LOOP语句、WHILE语句、FOR语句和REPEAT语句。LOOP语句循环执行一系列语句,直到EXIT语句终止循环为止;WHILE语句循环检测一个条件表达式,当表达式的值为TRUE时就执行循环体的语句;FOR语句对一系列语句重复执行指定次数;REPEAT语句重复执行一系列语句直至达到条件表达式的限制要求。
1.LOOP语句
LOOP语句实现对一系列语句的重复执行,是循环语句的最简单形式。它没有明显的终点,必须借助EXIT语句来跳出循环。LOOP语句的语法格式如下:

【例2-29】LOOP语句用法举例。

第5~11行是一个LOOP循环,每次循环都打印参数a的值,并将a的值减1,直到a小于等于0为止。
2.WHILE语句
WHILE语句在每次循环开始以前,先计算条件表达式,若该条件表达式的值为TRUE,则语句序列被执行一次,然后控制重新回到循环顶部;若条件表达式的值为FALSE,则结束循环。当然,也可以通过EXIT语句来终止循环。WHILE语句的语法格式如下:

【例2-30】WHILE语句用法举例。

这个例子的功能与例2-29相同,只是使用了WHILE语句。
3.FOR语句
当FOR语句执行时,首先检查下限表达式的值是否小于上限表达式的值,如果下限数值大于上限数值,则不执行循环体。否则,将下限数值赋予循环计数器(如果语句中使用了REVERSE关键字,则把上限数值赋给循环计数器);然后执行循环体内的语句序列;执行完后,循环计数器值加1(如果有REVERSE关键字,则减1);检查循环计数器的值,若仍在循环范围内,则重新继续执行循环体;如此循环,直到循环计数器的值超出循环范围。同样,也可以通过EXIT语句来终止循环。FOR语句的语法格式如下:

循环计数器是一个标识符,它类似于一个变量,但是不能被赋值,且作用域仅限于FOR语句内部。下限表达式和上限表达式用来确定循环的范围,它们的类型必须和整型兼容。循环范围是在循环开始之前确定的,即使在循环过程中下限表达式或上限表达式的值发生了改变,也不会引起循环范围的变化。
【例2-31】FOR语句用法举例。


这个例子的功能也与例2-29相同,只是使用了FOR语句。
FOR语句中的循环计数器可与当前程序块内的参数或变量同名,这时该同名的参数或变量在FOR语句的范围内被屏蔽。
【例2-32】FOR语句中的循环计数器与当前程序块内的参数或变量同名举例。

此例中,循环计数器v1与DATE类型的变量v1同名。在FOR语句内,PRINT语句将v1当作循环计数器。而FOR语句外的PRINT语句则将v1当作DATE类型的变量。
4.REPEAT语句
REPEAT语句用于重复执行一条或多条语句。REPEAT语句的语法格式如下:

【例2-33】REPEAT语句用法举例。

5.EXIT语句
EXIT语句与循环语句一起使用,用于终止其所在循环语句的执行,将控制转移到该循环语句外的下一个语句继续执行。注意:EXIT语句必须出现在一个循环语句中,否则将报错。EXIT语句的语法格式如下:

当EXIT后面的标号名省略时,该语句将直接终止包含它的那条循环语句;当EXIT后面带有标号名时,该语句用于终止标号名所标识的那条循环语句。需要注意的是,该标号名所标识的语句必须是循环语句,并且EXIT语句必须出现在此循环语句中。当EXIT语句位于多重循环中时,可以用该功能来终止其中的任何一重循环。
当WHEN子句省略时,EXIT语句无条件地终止该循环语句;否则,先计算WHEN子句中的条件表达式,当条件表达式的值为TRUE时,终止该循环语句。
【例2-34】不带标号名的EXIT语句举例。

运行结果为:

【例2-35】带标号名的EXIT语句举例。


运行结果为:

6.CONTINUE语句
CONTINUE语句的作用是退出本次循环,并且将语句控制转移到下一次循环或者指定标签的循环的开始位置,继续执行。CONTINUE语句的语法格式如下:

若CONTINUE后没有跟WHEN子句,则无条件立即退出本次循环,并且将语句控制转移到下一次循环或者指定标签的循环的开始位置,继续执行。
【例2-36】CONTINUE语句举例。

运行结果为:


CONTINUE WHEN语句的作用是当WHEN后面的条件满足时,将语句控制转移到下一次循环或者指定标签的循环的开始位置并继续执行。每次循环到达CONTINUE WHEN时,都会对WHEN的条件表达式进行计算,如果值为FALSE,则CONTINUE WHEN对应的语句不会被执行。为了防止出现死循环,可以将WHEN的条件设置为一个值肯定为TRUE的表达式。
【例2-37】CONTINUE WHEN语句举例。

运行结果为:

7.FORALL语句
FORALL语句的作用是将数据从一个集合传送给指定的使用集合的表,即当需要对数据表进行批量INSERT、UPDATE和DELETE 操作时,可以使用FORALL语句,这样不仅可以简化代码,并且可以优化数据操作的性能。需要注意的是,优化处理会影响游标的属性值,导致其不可使用。可以通过dm.ini配置文件中的USE_FORALL_ATTR参数控制是否进行优化处理,值为0表示可以优化,不使用游标属性;值为1表示不优化,使用游标属性,默认值为0。其语法格式如下:


其中,SAVE EXCEPTIONS设定,即使一些DML语句失败,也直到FORALL语句执行结束才抛出异常;INDICES OF <集合>表示跳过集合中没有赋值的元素,可用于指向稀疏数组的实际下标;VALUES OF <集合>把该集合中的值作为下标。
(1)用法1。

说明:①循环计算器是被遍历的数组元素的下标。②下标必须是连续的,否则执行会报错。③执行的SQL语句只能有一个。
【例2-38】创建表t_student,并批量插入数据。
步骤1:创建表t_student。

步骤2:批量插入数据。

(2)用法2。
在用法1中,如果数组中的数据下标不连续,则执行FORALL语句时会发生错误,如下面的代码:


为了解决上述问题,需要使用INDICES OF和VALUES OF两个子句,INDICES OF子句语法格式如下。

说明:①循环计算器是被遍历的数组元素的下标。②INDICES OF可以是循环跳过的没有赋值的元素,被赋予NULL也算有值。③BETWEEN 下限 AND 上限子句是可选的,作用是把子句的“下限”到“上限”范围之内的数值与数组元素下标做个交集,并遍历。这个交集可能是数组的全部元素,也可能是部分元素,或者为空。如果不指定,就遍历数组全部元素。④执行的SQL语句只能是一条。
【例2-39】INDICES OF用法举例。注意运行下面代码之前,先删除表t_student中的数据。

(3)用法3。
VALUES OF子句语法格式如下。

说明:①循环计算器是被遍历元素的值,且该集合值的类型只能是PLS_INTEGER或者BINARY_INTEGER;②执行的SQL语句只能是一条。
【例2-40】VALUES OF用法举例。
