This form of <literal>FOR</literal> creates a loop that iterates over a range
of integer values. The variable
<replaceable>name</replaceable> is automatically defined as type
<type>integer</type> and exists only inside the loop (any existing
definition of the variable name is ignored within the loop).
The two expressions giving
the lower and upper bound of the range are evaluated once when entering
the loop. If the <literal>BY</literal> clause isn't specified the iteration
step is 1, otherwise it's the value specified in the <literal>BY</literal>
clause, which again is evaluated once on loop entry.
If <literal>REVERSE</literal> is specified then the step value is
subtracted, rather than added, after each iteration.
</para>
<para>
Some examples of integer <literal>FOR</literal> loops:
<programlisting>
FOR i IN 1..10 LOOP
-- i will take on the values 1,2,3,4,5,6,7,8,9,10 within the loop
END LOOP;
FOR i IN REVERSE 10..1 LOOP
-- i will take on the values 10,9,8,7,6,5,4,3,2,1 within the loop
END LOOP;
FOR i IN REVERSE 10..1 BY 2 LOOP
-- i will take on the values 10,8,6,4,2 within the loop
END LOOP;
</programlisting>
</para>
<para>
If the lower bound is greater than the upper bound (or less than,
in the <literal>REVERSE</literal> case), the loop body is not
executed at all. No error is raised.
</para>
<para>
If a <replaceable>label</replaceable> is attached to the
<literal>FOR</literal> loop then the integer loop variable can be
referenced with a qualified name, using that
<replaceable>label</replaceable>.
</para>
</sect3>
</sect2>
<sect2 id="plpgsql-records-iterating">
<title>Looping through Query Results</title>
<para>
Using a different type of <literal>FOR</literal> loop, you can iterate through
the results of a query and manipulate that data
accordingly. The syntax is:
<synopsis>
<optional> <<<replaceable>label</replaceable>>> </optional>
FOR <replaceable>target</replaceable> IN <replaceable>query</replaceable> LOOP
<replaceable>statements</replaceable>
END LOOP <optional> <replaceable>label</replaceable> </optional>;
</synopsis>
The <replaceable>target</replaceable> is a record variable, row variable,
or comma-separated list of scalar variables.
The <replaceable>target</replaceable> is successively assigned each row
resulting from the <replaceable>query</replaceable> and the loop body is
executed for each row. Here is an example:
<programlisting>
CREATE FUNCTION refresh_mviews() RETURNS integer AS $$
DECLARE
mviews RECORD;
BEGIN
RAISE NOTICE 'Refreshing all materialized views...';
FOR mviews IN
SELECT n.nspname AS mv_schema,
c.relname AS mv_name,
pg_catalog.pg_get_userbyid(c.relowner) AS owner
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON (n.oid = c.relnamespace)
WHERE c.relkind = 'm'
ORDER BY 1
LOOP
-- Now "mviews" has one record with information about the materialized view
RAISE NOTICE 'Refreshing materialized view %.% (owner: %)...',
quote_ident(mviews.mv_schema),
quote_ident(mviews.mv_name),
quote_ident(mviews.owner);
EXECUTE format('REFRESH MATERIALIZED VIEW %I.%I', mviews.mv_schema, mviews.mv_name);
END LOOP;
RAISE NOTICE 'Done refreshing materialized views.';
RETURN 1;
END;
$$ LANGUAGE plpgsql;
</programlisting>
If the loop is terminated by an <literal>EXIT</literal> statement, the last
assigned row value is still accessible after the loop.
</para>
<para>
The <replaceable>query</replaceable> used in this type of <literal>FOR</literal>
statement can be any SQL command that returns rows to the caller: