循环语句主要用于反复执行一段操作,有以下几种形式:

  • 基本 LOOP

  • FOR LOOP

  • 用于游标的 FOR LOOP

  • WHILE LOOP

用于退出整个循环的声明包括:

  • EXIT

  • EXIT WHEN

用于退出本轮循环的声明为:

  • CONTINUE

  • CONTINUE WHEN

EXIT, EXIT WHEN, CONTINUE 和 CONTINUE WHEN 用于退出循环,可以放置在循环中的任何位置。 这是推荐的退出循环的方法。 虽然 GOTO 同样可以退出循环,但要避免使用这种方式。 EXIT 语句会将控制转移到 LOOP 结束处; CONTINUE 语句会退出循环的当前迭代,并将控制转移到下次迭代开始处;EXIT 和 CONTINUE 都可以跟一个可选的 WHEN 子句,其中可以指定一个提交。

如果是多层的嵌套循环,推荐给循环打上标签,这样会增加可读性。

基本 LOOP

基本的 LOOP 语句会重复执行一序列语句。基本 LOOP 的语句结构如下:

  1. [ label ] LOOP
  2. statements
  3. END LOOP [ label ];

使用 LOOP 循环语句,statements 语句会循环执行。为了避免死循环,LOOP 和 END LOOP 之间的语句中,至少要有一个语句包含 EXIT 语句;否则 LOOP 语句会一直重复永不停止。

EXIT 语句可以带一个可选的 WHEN 子句,表示当条件为 TRUE 的时候,执行 EXIT 语句并将控制跳转到的 END LOOP 语句后。

EXIT 语句

EXIT 语句表示无条件退出当前循环。

示例如下:

  1. obclient> DECLARE
  2. -> cnt NUMBER := 0;
  3. -> BEGIN
  4. -> LOOP
  5. -> DBMS_OUTPUT.PUT_LINE ('INSIDE: ' || TO_CHAR(cnt));
  6. -> cnt := cnt + 1;
  7. -> IF cnt > 5 THEN
  8. -> EXIT;
  9. -> END IF;
  10. -> END LOOP;
  11. -> DBMS_OUTPUT.PUT_LINE('OUTSIDE: ' || TO_CHAR(cnt));
  12. -> END;
  13. -> /
  14. Query OK, 0 rows affected (0.03 sec)
  15. INSIDE: 0
  16. INSIDE: 1
  17. INSIDE: 2
  18. INSIDE: 3
  19. INSIDE: 4
  20. INSIDE: 5
  21. OUTSIDE: 6

EXIT WHEN 语句

当 WHEN 字句的条件为 TRUE 时,EXIT WHEN 语句用于退出当前循环。示例如下:

  1. obclient> DECLARE
  2. -> cnt NUMBER := 0;
  3. -> BEGIN
  4. -> LOOP
  5. -> DBMS_OUTPUT.PUT_LINE ('INSIDE: ' || TO_CHAR(cnt));
  6. -> cnt := cnt + 1;
  7. -> EXIT WHEN cnt >5;
  8. -> END LOOP;
  9. -> DBMS_OUTPUT.PUT_LINE('OUTSIDE: ' || TO_CHAR(cnt));
  10. -> END;
  11. -> /
  12. Query OK, 0 rows affected (0.03 sec)
  13. INSIDE: 0
  14. INSIDE: 1
  15. INSIDE: 2
  16. INSIDE: 3
  17. INSIDE: 4
  18. INSIDE: 5
  19. OUTSIDE: 6

CONTINUE 语句

CONTINUE 语句用来退出本次循环, 即略过从 CONTINUE 开始直到循环结束的代码,从循环头开始继续下一次。

  1. obclient> DECLARE
  2. -> cnt NUMBER := 0;
  3. -> BEGIN
  4. -> LOOP
  5. -> cnt := cnt + 1;
  6. -> IF cnt < 4 THEN
  7. -> CONTINUE;
  8. -> END IF;
  9. -> DBMS_OUTPUT.PUT_LINE ('INSIDE: ' || TO_CHAR(cnt));
  10. -> EXIT WHEN cnt >5;
  11. -> END LOOP;
  12. -> DBMS_OUTPUT.PUT_LINE('OUTSIDE: ' || TO_CHAR(cnt));
  13. -> END;
  14. -> /
  15. Query OK, 0 rows affected (0.03 sec)
  16. INSIDE: 4
  17. INSIDE: 5
  18. INSIDE: 6
  19. OUTSIDE: 6

CONTINUE WHEN 语句

CONTINUE WHEN 语句同样是用于退出本次循环, 但只有在 WHEN 子句为 TRUE 的时候才会执行。

示例如下:

  1. obclient> DECLARE
  2. -> cnt NUMBER := 0;
  3. -> BEGIN
  4. -> LOOP
  5. -> cnt := cnt + 1;
  6. -> CONTINUE WHEN cnt < 4;
  7. -> DBMS_OUTPUT.PUT_LINE ('INSIDE: ' || TO_CHAR(cnt));
  8. -> EXIT WHEN cnt >5;
  9. -> END LOOP;
  10. -> DBMS_OUTPUT.PUT_LINE('OUTSIDE: ' || TO_CHAR(cnt));
  11. -> END;
  12. -> /
  13. Query OK, 0 rows affected (0.03 sec)
  14. INSIDE: 4
  15. INSIDE: 5
  16. INSIDE: 6
  17. OUTSIDE: 6

FOR LOOP 语句

FOR LOOP 会针对一个索引值范围,循环执行一段代码。 语法如下:

  1. [ label ] FOR index IN [ REVERSE ] lower_bound..upper_bound LOOP
  2. statements
  3. END LOOP [ label ];

如下例所示,不加 REVERSE 子句时, index 会从 lower_bound 递增至 upper_bound;使用 REVERSE 子句时, index 会从 lower_bound 递减至 upper_bound。

  1. obclient> BEGIN
  2. -> FOR i IN 1..5 LOOP
  3. -> DBMS_OUTPUT.PUT_LINE (i);
  4. -> END LOOP;
  5. -> END;
  6. -> /
  7. Query OK, 0 rows affected (0.03 sec)
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. obclient> BEGIN
  14. -> FOR i IN REVERSE 1..5 LOOP
  15. -> DBMS_OUTPUT.PUT_LINE (i);
  16. -> END LOOP;
  17. -> END;
  18. -> /
  19. Query OK, 0 rows affected (0.03 sec)
  20. 5
  21. 4
  22. 3
  23. 2
  24. 1

WHILE LOOP 语句

WHILE LOOP 是另外一个循环控制的形式,会在判断条件结果为 TRUE 的时候,重复执行一序列语句。如果条件结果为 FALSE 了,则退出循环。语法结构如下:

  1. [ label ] WHILE condition LOOP
  2. statements
  3. END LOOP [ label ];

只要检测 contidion 值为 TRUE,循环就会继续,直至 contidion 值为 FALSE 或者 NULL 为止。

  1. obclient> DECLARE
  2. -> cnt NUMBER := 0;
  3. -> BEGIN
  4. -> WHILE cnt < 3 LOOP
  5. -> DBMS_OUTPUT.PUT_LINE (cnt);
  6. -> cnt := cnt + 1;
  7. -> END LOOP;
  8. -> END;
  9. -> /
  10. Query OK, 0 rows affected (0.02 sec)
  11. 0
  12. 1
  13. 2