TRY / CATCH в PostgreSQL

—

от автора

Во встроенном процедурном языке 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:

Имя

Тип

Описание

RETURNED_SQLSTATE

text

код исключения

COLUMN_NAME

text

имя столбца, относящегося к исключению

CONSTRAINT_NAME

text

имя ограничения целостности, относящегося к исключению

PG_DATATYPE_NAME

text

имя типа данных, относящегося к исключению

MESSAGE_TEXT

text

текст основного сообщения исключения

TABLE_NAME

text

имя таблицы, относящейся к исключению

SCHEMA_NAME

text

имя схемы, относящейся к исключению

PG_EXCEPTION_DETAIL

text

текст детального сообщения исключения (если есть)

PG_EXCEPTION_HINT

text

текст подсказки к исключению (если есть)

PG_EXCEPTION_CONTEXT

text

строки текста, описывающие стек вызовов в момент исключения

Пример обработки исключения

В качестве примера будет рассмотрена обработка ошибки деления на ноль в функции 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 


ссылка на оригинал статьи https://habr.com/ru/post/657667/