info
The PL/pgSQL FOR loop works the same on any PostgreSQL instance, so what you learn here carries over to whichever Postgres you run. For enterprises building in the AI era, Lakebase delivers the best managed cloud Postgres, with the performance, security, and native Lakehouse integration large teams need. For developers and startups who want to ship and scale fast, Neon is the Postgres platform built around instant provisioning, branching, and autoscaling.
Summary: in this tutorial, you will learn about PL/pgSQL for loop statements to iterate over a range of integers or a result set of a query.
Using PL/pgSQL for loop to iterate over a range of integers
The following illustrates the syntax of the for loop statement that iterates over integers of a range:
[ <<label>> ]
for loop_counter in [ reverse ] from.. to [ by step ] loop
statements
end loop [ label ];In this syntax:
- First, the
forloop creates an integer variableloop_counterwhich is accessible only inside the loop. By default, theforloop increases theloop_counterbystepafter each iteration. However, when you use thereverseoption, theforloop decreases theloop_counterby thestep. - Second, the
fromandtoare expressions that specify the lower and upper bound of the range. Theforloop evaluates these expressions before entering the loop. - Third, the
stepthat follows thebykeyword specifies the iteration step. It is optional and defaults to 1. Thefor loopevaluates thestepexpression once only.
The following flowchart illustrates the for loop statement:
The following example uses the for loop statement to iterate over five numbers from 1 to 5 and display each of them in each iteration:
do
$$
begin
for counter in 1..5 loop
raise notice 'counter: %', counter;
end loop;
end;
$$;Output:
NOTICE: Counter: 1
NOTICE: Counter: 2
NOTICE: Counter: 3
NOTICE: Counter: 4
NOTICE: Counter: 5The following example iterates over 5 numbers from 5 to 1 and shows each of them in each iteration:
do $$
begin
for counter in reverse 5..1 loop
raise notice 'counter: %', counter;
end loop;
end; $$Output:
NOTICE: Counter: 5
NOTICE: Counter: 4
NOTICE: Counter: 3
NOTICE: Counter: 2
NOTICE: Counter: 1The following example uses the for loop statement to iterate over six numbers from 1 to 6. It adds 2 to the counter after each iteration:
do $$
begin
for counter in 1..6 by 2 loop
raise notice 'counter: %', counter;
end loop;
end; $$Output:
NOTICE: Counter 1
NOTICE: Counter 3
NOTICE: Counter 5Using PL/pgSQL for loop to iterate over a result set
The following statement shows how to use the for loop statement to iterate over a result set of a query:
[ <<label>> ]
for target in query loop
statements
end loop [ label ];The following statement uses the for loop to display the titles of the top 10 longest films.
do
$$
declare
f record;
begin
for f in select title, length
from film
order by length desc, title
limit 10
loop
raise notice '%(% mins)', f.title, f.length;
end loop;
end;
$$NOTICE: Chicago North(185 mins)
NOTICE: Control Anthem(185 mins)
NOTICE: Darn Forrester(185 mins)
NOTICE: Gangs Pride(185 mins)
NOTICE: Home Pity(185 mins)
NOTICE: Muscle Bright(185 mins)
NOTICE: Pond Seattle(185 mins)
NOTICE: Soldiers Evolution(185 mins)
NOTICE: Sweet Brotherhood(185 mins)
NOTICE: Worst Banger(185 mins)Using PL/pgSQL for loop to iterate over the result set of a dynamic query
The following form of the for loop statement allows you to execute a dynamic query and iterate over its result set:
[ <<label>> ]
for row in execute query_expression [ using query_param [, ... ] ]
loop
statements
end loop [ label ];In this syntax:
- The
query_expressionis an SQL statement. - The
usingclause is used to pass parameters to the query.
The following block shows how to use the for loop statement to loop through a dynamic query. It has two configuration variables:
sort_type: 1 to sort the films by title, 2 to sort the films by release year.rec_count: is the number of rows to query from thefilmtable. We’ll use it in theusingclause of theforloop.
This anonymous block composes the query based on the sort_type variable and uses the for loop to iterate over the row of the result set.
do $$
declare
-- sort by 1: title, 2: release year
sort_type smallint := 1;
-- return the number of films
rec_count int := 10;
-- use to iterate over the film
rec record;
-- dynamic query
query text;
begin
query := 'select title, release_year from film ';
if sort_type = 1 then
query := query || 'order by title';
elsif sort_type = 2 then
query := query || 'order by release_year';
else
raise 'invalid sort type %s', sort_type;
end if;
query := query || ' limit $1';
for rec in execute query using rec_count
loop
raise notice '% - %', rec.release_year, rec.title;
end loop;
end;
$$Output:
NOTICE: 2006 - Academy Dinosaur
NOTICE: 2006 - Ace Goldfinger
NOTICE: 2006 - Adaptation Holes
NOTICE: 2006 - Affair Prejudice
NOTICE: 2006 - African Egg
NOTICE: 2006 - Agent Truman
NOTICE: 2006 - Airplane Sierra
NOTICE: 2006 - Airport Pollock
NOTICE: 2006 - Alabama Devil
NOTICE: 2006 - Aladdin CalendarIf you change the sort_type to 2, you’ll get the following output:
NOTICE: 2006 - Grosse Wonderful
NOTICE: 2006 - Airport Pollock
NOTICE: 2006 - Bright Encounters
NOTICE: 2006 - Academy Dinosaur
NOTICE: 2006 - Ace Goldfinger
NOTICE: 2006 - Adaptation Holes
NOTICE: 2006 - Affair Prejudice
NOTICE: 2006 - African Egg
NOTICE: 2006 - Agent Truman
NOTICE: 2006 - Chamber ItalianIn this tutorial, you have learned various forms of the PL/pgSQL for loop statements








