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;

Leave a reply

Your email address will not be published. Required fields are marked *