
Во встроенном процедурном языке PL/pgSQL для СУБД PostgreSQL отсутствуют привычные операторы TRY / CATCH для для перехвата исключений возникающих в коде во время выполнения. Аналогом является оператор EXCEPTION, который используется в конструкции:
BEGIN -- код, в котором может возникнуть исключение EXCEPTION WHEN OTHERS -- аналог catch THEN -- код, обрабатывающий исключение END
Если необходимо обработать только конкретную ошибку, то в условии WHEN нужно указать идентификатор или код конкретной ошибки:
BEGIN -- код, в котором может возникнуть исключение EXCEPTION WHEN '<идентификатор_или_код_ошибки>' THEN -- код, обрабатывающий исключение END
Внутри секции EXCEPTION код ошибки можно получить из переменной SQLSTATE, а текст ошибки из переменной SQLERRM:
BEGIN -- код, в котором может возникнуть исключение EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'ERROR CODE: %. MESSAGE TEXT: %', SQLSTATE, SQLERRM; END
Более подробную информацию по исключению можно получить командой GET STACKED DIAGNOSTICS:
BEGIN -- код, в котором может возникнуть исключение EXCEPTION WHEN OTHERS THEN GET STACKED DIAGNOSTICS err_code = RETURNED_SQLSTATE, -- код ошибки msg_text = MESSAGE_TEXT, -- текст ошибки exc_context = PG_CONTEXT, -- контекст исключения msg_detail = PG_EXCEPTION_DETAIL, -- подробный текст ошибки exc_hint = PG_EXCEPTION_HINT; -- текст подсказки к исключению RAISE NOTICE 'ERROR CODE: % MESSAGE TEXT: % CONTEXT: % DETAIL: % HINT: %', err_code, msg_text, exc_context, msg_detail, exc_hint; END
Полный список переменных, которые можно получить командой GET STACKED DIAGNOSTICS:
Имя | Тип | Описание |
|
| код исключения |
|
| имя столбца, относящегося к исключению |
|
| имя ограничения целостности, относящегося к исключению |
|
| имя типа данных, относящегося к исключению |
|
| текст основного сообщения исключения |
|
| имя таблицы, относящейся к исключению |
|
| имя схемы, относящейся к исключению |
|
| текст детального сообщения исключения (если есть) |
|
| текст подсказки к исключению (если есть) |
|
| строки текста, описывающие стек вызовов в момент исключения |
Пример обработки исключения
В качестве примера будет рассмотрена обработка ошибки деления на ноль в функции catch_exception:
CREATE OR REPLACE FUNCTION catch_exception ( arg_1 int, arg_2 int, OUT res int ) LANGUAGE plpgsql AS $$ DECLARE err_code text; msg_text text; exc_context text; BEGIN BEGIN res := arg_1 / arg_2; EXCEPTION WHEN OTHERS THEN res := 0; GET STACKED DIAGNOSTICS err_code = RETURNED_SQLSTATE, msg_text = MESSAGE_TEXT, exc_context = PG_CONTEXT; RAISE NOTICE 'ERROR CODE: % MESSAGE TEXT: % CONTEXT: %', err_code, msg_text, exc_context; END; END; $$;
Вызов функции catch_exception со значением 0 в качестве второго параметра вызовет ошибку деления на ноль:
DO $$ DECLARE res int; BEGIN SELECT e.res INTO res FROM catch_exception(4, 0) AS e; RAISE NOTICE 'Result: %', res; END; $$;
Результаты обработки ошибки будут выведены на консоль:
ERROR CODE: 22012 MESSAGE TEXT: деление на ноль CONTEXT: функция PL/pgSQL catch_exception(integer,integer), строка 14, оператор GET STACKED DIAGNOSTICS SQL-оператор: "SELECT e.res FROM catch_exception(4, 0) AS e" функция PL/pgSQL inline_code_block, строка 5, оператор SQL-оператор Result: 0
