<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> <<<replaceable>label</replaceable>>> </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> ... </optional> THEN
<replaceable>handler_statements</replaceable>
... </optional>
END;
</synopsis>
</para>
<para>
If no error occurs, this form of block simply executes all the
<replaceable>statements</replaceable>, and then control passes
to the next statement after <literal>END</literal>. But if an error
occurs within the <replaceable>statements</replaceable>, further
processing of the <replaceable>statements</replaceable> is
abandoned, and control passes to the <literal>EXCEPTION</literal> list.
The list is searched for the first <replaceable>condition</replaceable>
matching the error that occurred. If a match is found, the
corresponding <replaceable>handler_statements</replaceable> are
executed, and then control passes to the next statement after
<literal>END</literal>. If no match is found, the error propagates out
as though the <literal>EXCEPTION</literal> clause were not there at all:
the error can be caught by an enclosing block with
<literal>EXCEPTION</literal>, or if there is none it aborts processing
of the function.
</para>
<para>
The <replaceable>condition</replaceable> names can be any of
those shown in <xref linkend="errcodes-appendix"/>. A category
name matches any error within its category. The special
condition name <literal>OTHERS</literal> matches every error type except
<literal>QUERY_CANCELED</literal> and <literal>ASSERT_FAILURE</literal>.
(It is possible, but often unwise, to trap those two error types
by name.) Condition names are
not case-sensitive. Also, an error condition can be specified
by <literal>SQLSTATE</literal> code; for example these are equivalent:
<programlisting>
WHEN division_by_zero THEN ...
WHEN SQLSTATE '22012' THEN ...
</programlisting>
</para>
<para>
If a new error occurs within the selected
<replaceable>handler_statements</replaceable>, it cannot be caught
by this <literal>EXCEPTION</literal> clause, but is propagated out.
A surrounding <literal>EXCEPTION</literal> clause could catch it.
</para>
<para>
When an error is caught by an <literal>EXCEPTION</literal> clause,
the local variables of the <application>PL/pgSQL</application> function
remain as they were when the error occurred, but all changes
to persistent database state within the block are rolled back.
As an example, consider this fragment:
<programlisting>
INSERT INTO mytab(firstname, lastname) VALUES('Tom', 'Jones');
BEGIN
UPDATE mytab SET firstname = 'Joe' WHERE lastname = 'Jones';
x := x + 1;
y := x / 0;
EXCEPTION
WHEN division_by_zero THEN
RAISE NOTICE 'caught division_by_zero';
RETURN x;
END;
</programlisting>
When control reaches the assignment to <literal>y</literal>, it will
fail with a <literal>division_by_zero</literal> error. This will be caught by
the <literal>EXCEPTION</literal>