Home Explore Blog CI



postgresql

35th chunk of `doc/src/sgml/plpgsql.sgml`
03d176430467718d6e57780af68132cdb7f652942074018f0000000100000fa3
 much like a <literal>FOR</literal> loop,
     but instead of iterating through the rows returned by an SQL query,
     it iterates through the elements of an array value.
     (In general, <literal>FOREACH</literal> is meant for looping through
     components of a composite-valued expression; variants for looping
     through composites besides arrays may be added in future.)
     The <literal>FOREACH</literal> statement to loop over an array is:

<synopsis>
<optional> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </optional>
FOREACH <replaceable>target</replaceable> <optional> SLICE <replaceable>number</replaceable> </optional> IN ARRAY <replaceable>expression</replaceable> LOOP
    <replaceable>statements</replaceable>
END LOOP <optional> <replaceable>label</replaceable> </optional>;
</synopsis>
    </para>

    <para>
     Without <literal>SLICE</literal>, or if <literal>SLICE 0</literal> is specified,
     the loop iterates through individual elements of the array produced
     by evaluating the <replaceable>expression</replaceable>.
     The <replaceable>target</replaceable> variable is assigned each
     element value in sequence, and the loop body is executed for each element.
     Here is an example of looping through the elements of an integer
     array:

<programlisting>
CREATE FUNCTION sum(int[]) RETURNS int8 AS $$
DECLARE
  s int8 := 0;
  x int;
BEGIN
  FOREACH x IN ARRAY $1
  LOOP
    s := s + x;
  END LOOP;
  RETURN s;
END;
$$ LANGUAGE plpgsql;
</programlisting>

     The elements are visited in storage order, regardless of the number of
     array dimensions.  Although the <replaceable>target</replaceable> is
     usually just a single variable, it can be a list of variables when
     looping through an array of composite values (records).  In that case,
     for each array element, the variables are assigned from successive
     columns of the composite value.
    </para>

    <para>
     With a positive <literal>SLICE</literal> value, <literal>FOREACH</literal>
     iterates through slices of the array rather than single elements.
     The <literal>SLICE</literal> value must be an integer constant not larger
     than the number of dimensions of the array.  The
     <replaceable>target</replaceable> variable must be an array,
     and it receives successive slices of the array value, where each slice
     is of the number of dimensions specified by <literal>SLICE</literal>.
     Here is an example of iterating through one-dimensional slices:

<programlisting>
CREATE FUNCTION scan_rows(int[]) RETURNS void AS $$
DECLARE
  x int[];
BEGIN
  FOREACH x SLICE 1 IN ARRAY $1
  LOOP
    RAISE NOTICE 'row = %', x;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

SELECT scan_rows(ARRAY[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]);

NOTICE:  row = {1,2,3}
NOTICE:  row = {4,5,6}
NOTICE:  row = {7,8,9}
NOTICE:  row = {10,11,12}
</programlisting>
    </para>
   </sect2>

   <sect2 id="plpgsql-error-trapping">
    <title>Trapping Errors</title>

    <indexterm>
     <primary>exceptions</primary>
     <secondary>in PL/pgSQL</secondary>
    </indexterm>

    <para>
     By default, any error occurring in a <application>PL/pgSQL</application>
     function aborts execution of the function and the
     surrounding transaction.  You can trap errors and recover
     from them by using a <command>BEGIN</command> block with an
     <literal>EXCEPTION</literal> clause.  The syntax is an extension of the
     normal syntax for a <command>BEGIN</command> block:

<synopsis>
<optional> &lt;&lt;<replaceable>label</replaceable>&gt;&gt; </optional>
<optional> DECLARE
    <replaceable>declarations</replaceable> </optional>
BEGIN
    <replaceable>statements</replaceable>
EXCEPTION
    WHEN <replaceable>condition</replaceable> <optional> OR <replaceable>condition</replaceable> ... </optional> THEN
        <replaceable>handler_statements</replaceable>
    <optional> WHEN <replaceable>condition</replaceable> <optional> OR <replaceable>condition</replaceable> ...

Title: FOREACH Loop with Array Slices and Error Trapping
Summary
The FOREACH loop iterates through elements or slices of an array. Without the SLICE option, it iterates through individual array elements. With a positive SLICE value, it iterates through array slices of specified dimensions. Error trapping in PL/pgSQL functions can be achieved using a BEGIN block with an EXCEPTION clause, allowing the function to recover from errors without aborting the transaction.