
I while ago, I wrote, HERE, how I regularly see commonly asked questions appearing in forums relating to the same topic. Like with SELECT INTO from my previous posts or GROUP BY in this post, I also see lots of questions about the correct usage of different LOOPs and so I figured that I would write up an explanation of how to properly use them and then, again, I can reference this post’s URL in response to questions on this topic!
Side Note: For those that frequent this blog.. firstly, Thankyou! and secondly, no I haven’t moved away from Cloud topics. I have lots of ideas for posts over the coming months – I just occasionally enjoy spinning up an oracle database in my free tier account and writing some PL/SQL for a change. Incidentally it happened to serve multiple purposes 🙂
Contents
Oracle PL/SQL LOOPs
Loops are a fundamental part of PL/SQL, allowing you to execute a block of code multiple times. Oracle provides several different types of loops in PL/SQL and choosing the right one can make your code clearer, more efficient and easier to maintain. In this post, we’ll cover the main types of loops available in PL/SQL, when to use them and some common pitfalls to watch out for.
For the examples in this post, I will use the widely known “hr schema”. The entity-relationship diagram is as below.

LOOP statements, execute sequence of statements multiple times. The LOOP and END LOOP keywords enclose the statements. PL/SQL provides four kinds of LOOP statements:
- Basic
LOOP– In this loop structure, a sequence of statements is enclosed between theLOOPandEND LOOPstatements. At each iteration, the sequence of statements is executed and then control resumes at the top of the loop. WHILEloop – In this loop structure, a statement or group of statements repeat while a given condition remains true. It tests the condition before executing the loop body.FORloop – In this loop structure, a sequence of statements is executed multiple times and increments the code that manages the loop variable.- Cursor
FORloop – In this loop structure, you can loop through query results without manually opening, fetching and closing a cursor.
Basic LOOP
Syntax
A basic loop structure encloses a sequence of statements between the LOOP and END LOOP statements. With each iteration, the sequence of statements is executed and then control resumes at the top of the loop. In it’s most simplistic form, a basic LOOP uses the following expected syntax:
LOOP -- Code block that you wish to execute a number of timesEND LOOP;
An EXIT statement is used to break the loop whether the loop condition has been satisfied or not. This statement is particularly useful when you want to terminate the loop based on a pre-defined condition within the loop block. For instance, if you’re analyzing data in a loop and you encounter an anomaly that requires immediate attention, the EXIT statement allows you to exit the loop gracefully. It looks like this in the most basic syntax form:
LOOP -- Code block that you wish to execute a number of times IF condition THEN EXIT; END IF;END LOOP;
An EXIT WHEN statement can be used to break the loop in a more streamlined way. It looks like this in the most basic syntax form:
DECLARE -- Declare a variable and assign the number 1 variable NUMBER := 1;BEGIN -- Open a loop to iterate a seqence of statements LOOP -- Code block that you wish to execute a number of times variable := variable + 1; -- add 1 to the variable in each loop EXIT WHEN variable > 10; -- exit the loop when the variable has a value more than 10 (e.g iterate 10 times only) END LOOP;
Example
The following example uses a basic PL/SQL block to loop a counter variable and output the counter value.
DECLARE v_counter NUMBER := 1;BEGIN LOOP -- write counter value DBMS_OUTPUT.PUT_LINE('Counter value is: ' || v_counter); -- increment counter value v_counter := v_counter + 1; -- exit clause EXIT WHEN v_counter > 5; END LOOP;END;
An explanation of this example is below:
- I have declared a variable of type number name
v_counter. It is intialised with the value 1 - I used a basic
LOOPstatement to open a looped logic. Within each iteration of the loop I:- Output the value of the
v_countervariable - Increment the value of the
v_countervariable by 1
- Output the value of the
- An
EXIT WHENclause is added to ensure that the loop logic exits at the point in which thev_countervariable is more than 5.
The output is per the below screenshot:

WHILE loop
Syntax
A WHILE loop statement repeatedly executes a set of statements as long as a given condition remains true. It looks like this in the most basic syntax form:
WHILE condition loop -- Code block that you wish to execute a number of timesEND LOOP;
In a WHILE loop, you do not need to force an EXIT or EXIT WHEN (though you can based on any unhappy path scenarios there may be in your code). This design choice allows for a more streamlined flow of execution, as the loop will naturally continue iterating as long as the specified condition remains true. Such flexibility can be advantageous in situations where the loop is performing complex operations that may encompass various conditions or states, allowing for a more dynamic response to the data being processed.
Example
The following example is very similar to the example used in to show basic loop above. It loops a counter variable and output the counter value, but this time, an EXIT WHEN statement is not necessary as the WHILE loop controls the conditional run.
DECLARE v_counter NUMBER := 1;BEGIN WHILE v_counter <=5 LOOP -- write counter value DBMS_OUTPUT.PUT_LINE ('Counter values is: ' || v_counter); -- increment counter value v_counter := v_counter + 1; END LOOP;END;
An explanation of this example is below:
- I have declared a variable of type number name
v_counter. It is intialised with the value 1 - I used a
WHILEloop statement which has a condition to run only where the value ofv_counteris less than or equal to 5 to open a looped logic. Within each iteration of the loop I:- Output the value of the
v_countervariable - Increment the value of the
v_countervariable by 1
- Output the value of the
The output is per the below screenshot:

FOR loop
Syntax
A FOR loop is a repetition control structure that allows you to efficiently write a loop that needs to execute a specific number of times. In it’s most basic syntax form, it looks like this:
FOR counter IN start_value..end_value loop -- Code block that you wish to execute a number of timesEND LOOP;
Like in a WHILE loop, you do not need to force an EXIT or EXIT WHEN (though you can based on any unhappy path scenarios there may be in your code).
In a FOR loop, the condition start_value..end_value is evaluated. Where it is TRUE, the body of the loop is executed, allowing for repetitive operations based on the specified range. If it is FALSE, the body of the loop does not execute, and the flow of control jumps to the next statement in your PL/SQL logic. Whilst the loop is executing, the value of the counter variable is increased upon each iteration of the loop block, which plays a crucial role in tracking the number of times the loop has run. Each time, the condition will be evaluated again, providing a dynamic check that determines whether the loop should continue or terminate.
There are some special characteristics of a FOR loop:
- The
counter,start_valueandend_valuecan be literals, variables or expressions but must evaluate to numbers otherwise you will be met with aVALUE_ERROR - the
start_valuedoes not need to be 1, but, the loop counter increment must be 1
It is also possible to use a reverse FOR loop. As mentioned, by default, iteration of the loop proceeds from the initial value to the final value, allowing programmers to traverse elements in a sequential manner. However, in some scenarios, it may be more efficient or logical to traverse elements in the opposite direction. You can reverse this order by using the REVERSE keyword, which effectively alters the flow of the loop. In these cases, iteration of the loop proceeds the other way, starting from the last value and moving down to the first. After each iteration, the loop counter is decremented, which means that the program will continue executing the loop until it reaches the defined starting point. It looks like this:
FOR counter IN REVERSE start_value..end_value LOOP-- Code block that you wish to execute a number of timesEND LOOP;
Example
The following example is again very similar to the example used in to show basic loop and while loop above. It loops a counter variable and output the counter value, but this time, an EXIT WHEN statement is not necessary as the WHILE loop controls the conditional run.
DECLARE v_counter NUMBER := 1;BEGIN FOR i IN 1..5 LOOP DBMS_OUTPUT.PUT_LINE('Counter value is: ' || v_counter); END LOOP;END;
An explanation of this example is below:
- I used a
FORloop statement which has a condition to run only where the value of i is between 1 and 5 to open a looped logic. Within each iteration of the loop I:- Output the value of the
v_countervariable - It is not necessary to increment the value of i manually
- Output the value of the
The output is per the below screenshot:

cursor FOR loop
Syntax
You would use a CURSOR FOR LOOP when you want to fetch and process every record in a cursor efficiently and systematically. This control structure simplifies the retrieval of rows from a database by automatically handling the iteration through each record. The CURSOR FOR LOOP allows for an organised approach, facilitating operations on each record within its defined scope. The loop will terminate when all of the records have been fetched and processed. It looks like this:
FOR record_index IN cursor_name LOOP -- Code block that you wish to execute a number of timesEND LOOP;
Though, in reality, it really needs to look like this:
DECLARE CURSOR c1 IS SELECT row_name FROM table_name WHERE condition;BEGIN FOR rec in c1 LOOP -- Code block that you wish to execute a number of times END LOOP;END;
Example
The following example uses a cursor to return a SQL query result, loop about those results using a cursor FOR loop and output the Full name of all employees who have a location of Seattle.
DECLARE v_employee_count NUMBER; CURSOR c1 IS -- Example cursor for loop SELECT emp.first_name, emp.last_name FROM employees emp, departments dep, locations loc WHERE emp.department_id = dep.department_id AND dep.location_id = loc.location_id AND loc.city = 'Seattle';BEGIN v_employee_count := 0; FOR employees_rec in c1 LOOP v_employee_count := v_employee_count + 1; DBMS_OUTPUT.PUT_LINE('Full Name: ' || employees_rec.first_name || ' ' || employees_rec.last_name); END LOOP; DBMS_OUTPUT.PUT_LINE(''); DBMS_OUTPUT.PUT_LINE('Total Employees in Seattle: ' || v_employee_count);END;
An explanation of this example is below:
- I declared a variable
v_employee_countto keep a total of number of employees that are processed in the loop - I declared a cursor which returns all employees who are based in Seattle
- I initialised the
v_employee_countvariable with the value 0 - I used a cursor
FORloop statement which iterates all the records returned by the cursor. Within each iteration of the loop I:- Increment my variable
v_employee_countby 1 - Output the full name of each employee by concatenating
first_nameandlast_namefrom theemployees_recrecord together
- Increment my variable
- Finally (outside of the loop), I output the total employees based in Seattle, using my
v_employee_countvariable
The output is per the below screenshot:
