Обработка исключений в хранимых процедурах и анонимных блоках возможна только внутри конструкции
BEGIN
-- Тут располагается потенциально опасный код
EXCEPTION
WHEN '<идентификатор_ошибки>' THEN
-- Тут находится код, обрабатывающий исключение
END
Для того, чтобы обработать исключение, необходимо указать идентификатор ошибки, который будет обрабатываться. Коды всех ошибок и их идентификаторов можно найти на странице PostgreSQL Error Codes официальной документации.
К примеру, необходимо обрабатывать ситуацию, когда происходит запись двух одинаковых значений в уникальное поле таблицы
Выполнив нижеприведенный код:
DO $$
BEGIN
CREATE TABLE test_table(
name varchar UNIQUE
);
INSERT INTO test_table(name) VALUES('my name');
INSERT INTO test_table(name) VALUES('my name');
END $$;
получим исключение:
ERROR: duplicate key value violates unique constraint "test_table_name_key"
DETAIL: Key (name)=(my name) already exists.
CONTEXT: SQL statement "INSERT INTO test_table(name) VALUES('my name')"
PL/pgSQL function "inline_code_block" line 7 at SQL statement
по тексту исключения можно попробовать найти ошибку на странице PostgreSQL Error Codes, но это не всегда бывает возможно. Поэтому надо узнать код ошибки однозначно. Для этого надо вывести в лог значение специальной переменной SQLSTATE, которая и содержит искомый код.
DO $$
BEGIN
CREATE TABLE test_table(
name varchar UNIQUE
);
INSERT INTO test_table(name) VALUES('my name');
INSERT INTO test_table(name) VALUES('my name');
EXCEPTION
WHEN others THEN
RAISE NOTICE 'SQLSTATE: %', SQLSTATE;
RAISE;
END $$;
в логе виден код ошибки (23505):
NOTICE: SQLSTATE: 23505
ERROR: duplicate key value violates unique constraint "test_table_name_key"
DETAIL: Key (name)=(my name) already exists.
CONTEXT: SQL statement "INSERT INTO test_table(name) VALUES('my name')"
PL/pgSQL function "inline_code_block" line 7 at SQL statement
другое дело. По таблице кодов ошибок сразу находим идентификатор ошибки, который надо обрабатывать
Error Code Condition Name 23505 unique_violation
изменяю предыдущий код:
DO $$
BEGIN
CREATE TABLE test_table(
name varchar UNIQUE
);
INSERT INTO test_table(name) VALUES('my name');
INSERT INTO test_table(name) VALUES('my name');
EXCEPTION
WHEN unique_violation THEN
RAISE NOTICE 'Illegal operation: %', SQLERRM;
END $$;
Результат:
PL/pgSQL function "inline_code_block" line 3 at SQL statement
NOTICE: Illegal operation: duplicate key value violates unique constraint "test_table_name_key"
Исключительная ситуация обработана.
Совет
Бывают ситуацию, когда надо защититься от всех возможных ошибок, которые могут возникнуть. В этом случае поможет специальный идентификатор ошибки others. С помощью этого идентификатора можно ловить любые типы исключения, кроме query_canceled