PL/SQL by Example / FOR and WHILE loop
For cyclical repetition of a code block, PL/SQL provides the FOR and WHILE constructs. For the sake of completeness, I also mention the general LOOP at the end of the article, which I do not recommend using.
FOR
Basic loop with a fixed range. As in other languages, it is not necessary to explicitly declare the iteration variable; its scope is therefore limited only to the given loop. Incrementing happens automatically.
BEGIN
FOR i IN 1..5 LOOP
dbms_output.put(i);
END LOOP;
dbms_output.new_line; -- 12345
END;
Very often, the FOR loop is used to iterate through an array with a finite number of elements. In the following example, the keywords REVERSE, which reverses the direction of iteration, and EXIT WHEN, used for premature loop termination, are worth noting.
DECLARE
TYPE Number_TT IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
lt_Employee_ID Number_TT;
BEGIN
SELECT employee_id
BULK COLLECT INTO
lt_Employee_ID
FROM employees
WHERE (ROWNUM<11) -- limit to 10 rows
;
FOR i IN REVERSE 1..lt_Employee_ID.COUNT LOOP
dbms_output.put(lt_Employee_ID(i)||' ');
EXIT WHEN lt_Employee_ID(i)=105;
END LOOP;
dbms_output.new_line; -- 109 108 107 106 105
END;
WHILE
The WHILE loop does not have a specified fixed range; it is limited only by the condition at the beginning. The example shows one way to iterate through an interval of days.
DECLARE
-- interval boundaries
L_START CONSTANT DATE:=TO_DATE('4.1.2016', 'DD.MM.YYYY');
L_END CONSTANT DATE:=TO_DATE('7.1.2016', 'DD.MM.YYYY');
-- day serving as a counter
l_Day DATE;
BEGIN
l_Day:=L_START;
WHILE (l_Day<=L_END) LOOP
dbms_output.put(TO_CHAR(l_Day, 'DD')||' ');
l_Day:=l_Day+1;
END LOOP;
dbms_output.new_line; -- 04 05 06 07
END;
In certain situations, typically with multiple levels of nesting, naming the loop can be useful. Interruption is again triggered using the EXIT command followed by the label name.
DECLARE
-- it is suitable to use an integer type from PL/SQL as a counter
-- and the "safe" NOT NULL clause
i PLS_INTEGER NOT NULL:=1;
j PLS_INTEGER NOT NULL:=1;
BEGIN
<<outer_loop>>
WHILE (i<11) LOOP
WHILE (j<11) LOOP
dbms_output.put(i||j||' ');
EXIT outer_loop WHEN (j>2);
j:=j+1;
END LOOP;
i:=i+1;
END LOOP;
dbms_output.new_line; -- 11 12 13
END;
LOOP
General “infinite” loop without specification of either condition or range. Since Oracle 11g, PL/SQL has added support for CONTINUE and CONTINUE WHEN to proceed to the next iteration.
DECLARE
i PLS_INTEGER NOT NULL:=0;
BEGIN
LOOP
i:=i+1;
CONTINUE WHEN (i<3);
dbms_output.put(i||' ');
EXIT WHEN (i>4);
END LOOP;
dbms_output.new_line; -- 3 4 5
END;