目录
基本LOOP循环结构包含关键字LOOP和END LOOP之间的一系列语句,如下所示:
LOOP
sequence_of_statements
END LOOP;
执行语句序列,然后控制在循环顶部恢复。我们可以在基本循环中使用CONTINUE和CONTINUE-WHEN语句。要防止死循环,必须使用EXIT或EXIT-WHEN语句。
当遇到EXIT语句时,循环立即退出,并且控制传递到END LOOP之后的语句。
DECLARE
x NUMBER := 0;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE('Inside loop: x = ' || TO_CHAR(x));
x := x + 1;
IF x > 10 THEN
EXIT;
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE (' After loop: x = ' || TO_CHAR(x));
END;
/
遇到EXIT-WHEN语句时,先计算WHEN子句中的条件。如果条件为真,则循环完成,控制传递到END LOOP之后的语句。
DECLARE
x NUMBER := 0;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE ('Inside loop: x = ' || TO_CHAR(x));
x := x + 1;
EXIT WHEN x > 10;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('After loop: x = ' || TO_CHAR(x));
END;
/
您可以使用标签给循环命名。PL / SQL中的循环标签具有以下格式:
<<label_name>>
其中label_name是标签的名称,并且该循环标签紧接在LOOP语句之前出现:
<<all_emps>>
FOR emp_rec IN emp_cur
LOOP
...
END LOOP;
可选标签(由双尖括号括起来的未声明标识符)必须出现在LOOP语句的开头。标签名称也可以显示在LOOP语句的末尾。使用任何形式的EXIT语句,您不仅可以退出当前循环,而且可以退出任何封闭循环。
EXIT-WHEN与基本LOOP中的标签:
DECLARE
s PLS_INTEGER := 0;
i PLS_INTEGER := 0;
j PLS_INTEGER;
BEGIN
<<outer_loop>>
LOOP
i := i + 1;
j := 0;
<<inner_loop>>
LOOP
j := j + 1;
s := s + i * j;
EXIT inner_loop WHEN (j > 10);
EXIT outer_loop WHEN ((i * j) > 25);
END LOOP inner_loop;
END LOOP outer_loop;
DBMS_OUTPUT.PUT_LINE('The sum: ' || TO_CHAR(s));
END;
/
EXIT与FOR LOOP中的标签:
DECLARE
v_employees employees%ROWTYPE;
CURSOR c1 is SELECT * FROM employees;
BEGIN
OPEN c1;
<<outer_loop>>
FOR i IN 1..10 LOOP
-- Process data here
FOR j IN 1..10 LOOP
FETCH c1 INTO v_employees;
EXIT outer_loop WHEN c1%NOTFOUND;
-- Process data here
END LOOP;
END LOOP outer_loop;
CLOSE c1;
END;
/
有两种PL / SQL FOR循环:数字FOR循环和游标FOR循环。
数字FOR循环是传统的。当循环开始时,FOR循环的迭代次数是已知的。这里是数字FOR循环的一般语法:
FOR loop index IN [REVERSE] lowest number .. highest number
LOOP
executable statement(s)
END LOOP;
注意:您必须在LOOP和END LOOP关键字之间至少有一个可执行语句。
实例1:
-- FOR LOOP语句
BEGIN
FOR loop_counter IN 1 .. 10
LOOP
DBMS_OUTPUT.PUT_LINE(loop_counter);
END LOOP;
END;
/
-- 反转FOR LOOP语句
BEGIN
FOR loop_counter IN REVERSE 1 .. 10
LOOP
DBMS_OUTPUT.PUT_LINE(loop_counter);
END LOOP;
END;
/
实例2:
循环范围的边界可以是数字,变量或表达式,但它们必须求值为数字。
DECLARE
first INTEGER := 1;
last INTEGER := 10;
high INTEGER := 100;
low INTEGER := 12;
BEGIN
-- Bounds are numeric literals:
FOR j IN -5..5 LOOP
NULL;
END LOOP;
-- Bounds are numeric variables:
FOR k IN REVERSE first..last LOOP
NULL;
END LOOP;
FOR step IN 0..(TRUNC(high/low) * 2) LOOP
NULL;
END LOOP;
END;
/
实例3:
如果循环范围的下限大于上限,则不执行循环体。
-- 使用现有变量作为循环变量
DECLARE
i NUMBER := 5;
BEGIN
DBMS_OUTPUT.PUT_LINE ('Before loop, i is ' || TO_CHAR(i));
FOR i IN 1..3 LOOP -- 若为:FOR i IN 3..1 LOOP,则不执行循环体
DBMS_OUTPUT.PUT_LINE ('Inside loop, i is ' || TO_CHAR(i));
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Outside loop, i is ' || TO_CHAR(i));
END;
/
实例4:引用与内部计数器名称相同的外部计数器
DECLARE
i NUMBER := 5;
BEGIN
<<outer_loop>>
FOR i IN 1..3 LOOP
<<inner_loop>>
FOR i IN 1..3 LOOP
IF outer_loop.i = 2 THEN
DBMS_OUTPUT.PUT_LINE('outer: ' || TO_CHAR(outer_loop.i) || ' inner: ' || TO_CHAR(inner_loop.i));
END IF;
END LOOP inner_loop;
END LOOP outer_loop;
END;
/
游标FOR循环是与显式游标相关联的循环。下面是游标FOR循环的基本语法:
FOR record IN { cursor_name | (explicit SELECT statement) }
LOOP
executable statement(s)
END LOOP;
其中record是由PL / SQL使用%ROWTYPE属性对由cursor_name指定的游标隐式声明的记录。
实例:
DECLARE
CURSOR c_my IS SELECT id, room_number FROM occupancy;
my_rec c_my%ROWTYPE;
BEGIN
OPEN c_my;
LOOP
FETCH c_my INTO my_rec;
EXIT WHEN c_my%NOTFOUND;
update_bill(my_rec.id, my_rec.room_number);
END LOOP;
CLOSE c_my;
END;
/
使用ROWNUM的推荐方式:
SELECT ROWNUM, a.*
FROM (SELECT customers.*
FROM customers
WHERE customer_id > 4500
ORDER BY last_name) a;
只要条件为真,WHILE-LOOP语句就执行循环体中的语句:
WHILE condition LOOP
sequence_of_statements
END LOOP;
实例:
DECLARE
a number(2) := 10;
BEGIN
WHILE a < 20 LOOP
dbms_output.put_line('value of a: ' || a);
a := a + 1;
END LOOP;
END;
/