In PostgreSQL PL/pgSQL, EXCEPTION plays two distinct roles. First, it starts the error-handling section of a BEGIN … END block, allowing developers to trap specific runtime errors and execute recovery logic instead of aborting the session. Second, used with the RAISE statement (RAISE EXCEPTION), it deliberately throws an error, immediately aborting the current transaction block unless caught by an enclosing EXCEPTION handler. Both forms integrate with PostgreSQL’s transactional semantics: once an uncaught exception is raised, the transaction enters an aborted state and must be rolled back or ended. EXCEPTION blocks match errors by condition name (e.g., unique_violation) or SQLSTATE codes, support multiple OR-chained conditions, and default to WHEN OTHERS for a catch-all. Because EXCEPTION is PL/pgSQL-only, it cannot appear in plain SQL executed outside a function, DO block, or procedure. Raising an exception rolls back any changes made in the current block unless handled, so care is needed when nesting subtransactions (e.g., using SAVEPOINT).
- condition
(text or SQLSTATE) - Name such as unique_violation, division_by_zero, or a 5-char SQLSTATE code.- message
(text) - Required. Error string (can include format specifiers like %).- argN
(any) - Optional. Values to substitute into message.- USING option=value
- keyword pairs to set errcode, detail, hint, column, table, constraint, schema.RAISE, SAVEPOINT, TRY CATCH (SQL Server), DECLARE HANDLER (MySQL), PL/pgSQL error codes
PostgreSQL 7.0 (initial PL/pgSQL support)
EXCEPTION starts a catch block, while RAISE EXCEPTION actively throws a new error. Both interact but serve opposite roles: catching vs raising.
Yes. Chain conditions with OR, or write separate WHEN clauses for fine-grained handling.
Query the pg_catalog.pg_exception table or use the official documentation listing condition names and SQLSTATE codes.
Absolutely. Procedures written in PL/pgSQL use the same BEGIN … EXCEPTION … END syntax as functions.