Home Explore Blog CI



postgresql

33th chunk of `doc/src/sgml/plpgsql.sgml`
1caa55a4a1576e552a3815c506991bb4352c58fd4f1380080000000100000fa0
    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> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </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:
 

Title: FOR Loop Integer Variant Details and Looping Through Query Results
Summary
This section expands on the integer FOR loop, providing examples and clarifying behavior when the lower bound exceeds the upper bound. It also introduces another form of the FOR loop that iterates through the results of a query. The target variable is assigned each resulting row, and the loop body executes for each row. An example shows refreshing materialized views using this type of loop.