Sql

Postgresql exception: Postgres Pro Standard : Документация: 9.6: 39.6. Управляющие структуры : Компания Postgres Professional

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

© Habrahabr.ru

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

Исключение PostgreSQL

Резюме : в этом руководстве вы узнаете, как перехватывать исключения PostgreSQL в PL/pgSQL.

Введение в пункт об исключении PL/pgSQL

Когда в блоке возникает ошибка, PostgreSQL прерывает выполнение блока, а также окружающую транзакцию.

Чтобы устранить ошибку, вы можете использовать предложение исключения в блоке begin...end .

Ниже показан синтаксис исключение пункт:

 

<<метка>> объявить начинать заявления; исключение когда условие [или условие. ..] тогда обработать_исключение; [когда условие [или условие...] тогда обработать_исключение;] [когда другие тогда обрабатывать_другие_исключения; ] конец;

Язык кода: диалект PostgreSQL SQL и PL/pgSQL (pgsql)

Как это работает.

  • Во-первых, когда возникает ошибка между begin и исключение , PL/pgSQL останавливает выполнение и передает управление в список исключений.
  • Во-вторых, PL/pgSQL ищет первое условие , которое соответствует возникшей ошибке.
  • В-третьих, если есть совпадение, будут выполнены соответствующие операторы handle_exception . PL/pgSQL передает управление оператору после ключевого слова end .
  • Наконец, если совпадение не найдено, ошибка распространяется и может быть перехвачена исключение пункт вмещающего блока. В случае отсутствия окружающего блока с предложением exception PL/pgSQL прервет обработку.

Имена условия могут быть no_data_found в случае select оператор не возвращает ни одной строки или too_many_rows если select оператор возвращает более одной строки. Полный список имен условий можно найти на веб-сайте PostgreSQL.

Также возможно указать состояние ошибки с помощью Код SQLSTATE . Например, P0002 для no_data_found и P0003 для too_many_rows .

Как правило, вы перехватываете конкретное исключение и обрабатываете его соответствующим образом. Для обработки других исключений, а не того, которое вы указали в списке, вы можете использовать предложение , когда другие, а затем .

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

Для демонстрации мы будем использовать таблицу film из примера базы данных.

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

В следующем примере возникает ошибка, поскольку фильм с идентификатором 2000 не существует.

 

сделать $$ объявить запись записи; v_film_id интервал = 2000; начинать -- выбрать фильм выберите film_id, название в строгую запись из фильма где film_id = v_film_id; конец; $$ язык plpgsql;

Язык кода: диалект PostgreSQL SQL и PL/pgSQL (pgsql)

Вывод:

 

ОШИБКА: запрос не вернул строк КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 6 в операторе SQL Состояние SQL: P0002

Язык кода: сеанс оболочки (оболочка)

В следующем примере используется предложение исключения для перехвата исключения no_data_found и выдачи более значимого сообщения:

 

do $$ объявить запись записи; v_film_id интервал = 2000; начинать -- выбрать фильм выберите film_id, название в строгую запись из фильма где film_id = v_film_id; -- поймать исключение исключение когда no_data_found тогда вызвать исключение «фильм % не найден», v_film_id; конец; $$ язык plpgsql;

Язык кода: диалект PostgreSQL SQL и PL/pgSQL (pgsql)

Вывод:

 

ОШИБКА: фильм 2000 не найден КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 14 в RAISE Состояние SQL: P0001

Язык кода: Сеанс оболочки (оболочка)

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

В следующем примере показано, как обрабатывать исключение too_many_rows :

 

1 do $$ объявить запись записи; начинать -- выбрать фильм выберите film_id, название в строгую запись из фильма где заголовок LIKE 'A%'; исключение когда too_many_rows тогда вызвать исключение «Поисковой запрос возвращает слишком много строк»; конец; $$ язык plpgsql;

Язык кода: диалект PostgreSQL SQL и PL/pgSQL (pgsql)

Вывод:

 

ОШИБКА: Поисковый запрос возвращает слишком много строк КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 15 в RAISE Состояние SQL: P0001

Язык кода: Сеанс оболочки (оболочка)

В этом примере исключение too_many_rows возникает из-за того, что оператор select into возвращает более одной строки, в то время как он должен возвращать одну строку.

3) Обработка нескольких исключений

В следующем примере показано, как перехватывать несколько исключений:

 

do $$ объявить запись записи; v_length интервал = 90; начинать -- выбрать фильм выберите film_id, название в строгую запись из фильма где длина = v_длина; -- поймать исключение исключение когда sqlstate 'P0002' тогда вызвать исключение «фильм с длиной % не найден», v_length; когда sqlstate 'P0003' тогда поднять исключение «С длиной % не является уникальным», v_length; конец; $$ язык plpgsql;

Язык кода: диалект PostgreSQL SQL и PL/pgSQL (pgsql)

Вывод:

 

ОШИБКА: длина 90 не уникальна КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 17 в RAISE Состояние SQL: P0001

Язык кода: Сеанс оболочки (оболочка)

4) Обработка исключений в виде кодов SQLSTATE

Следующий пример аналогичен приведенному выше, за исключением того, что вместо условия используются коды SQLSTATE имена:

 

сделать $$ объявить запись записи; v_length интервал = 30; начинать -- выбрать фильм выберите film_id, название в строгую запись из фильма где длина = v_длина; -- поймать исключение исключение когда sqlstate 'P0002' тогда вызвать исключение «фильм с длиной % не найден», v_length; когда sqlstate 'P0003' тогда поднять исключение «С длиной % не является уникальным», v_length; конец; $$ язык plpgsql;

Язык кода: диалект PostgreSQL SQL и PL/pgSQL (pgsql)

Вывод:

 

ОШИБКА: фильм длиной 30 не найден КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 15 в RAISE Состояние SQL: P0001

Язык кода: Сеанс оболочки (оболочка)

Сводка

  • Используйте предложение exception в блоке begin. ..end для перехвата и обработки исключений.

Было ли это руководство полезным?

postgresql — ИСКЛЮЧЕНИЕ, КОГДА ДРУГИЕ ТОГДА НОЛЬ в Postgres

спросил

Изменено 2 года, 9 месяцев назад

Просмотрено 9к раз

У меня есть исключение в Oracle PL/SQL, которое необходимо перенести в PostgreSQL pl/pgsql. Ниже приведен вариант оракула

 ИСКЛЮЧЕНИЕ
КОГДА ДРУГИЕ ТОГДА
НУЛЕВОЙ;
 

Что такое вариант PL/PGSQL?

  • postgresql
  • исключение
  • plpgsql

1

Тот же синтаксис. Сравните 2 следующих исполнения:

 DO
$$
НАЧИНАТЬ
ПОВЫСИТЬ деление_на_ноль;
ИСКЛЮЧЕНИЕ
КОГДА ДРУГИЕ ТОГДА
НУЛЕВОЙ;
КОНЕЦ;
$$
ДЕЛАТЬ
 

А:

 ДО
$$
НАЧИНАТЬ
ПОВЫСИТЬ деление_на_ноль;
КОНЕЦ;
$$
ОШИБКА: Division_by_zero
КОНТЕКСТ: функция PL/pgSQL inline_code_block, строка 3 в RAISE
 

НЕ портировать как есть. Это ОШИБКА ВСЕГДА . Если вы ничего не делаете, по крайней мере, зарегистрируйте ошибку. Если это происходит в интерактивном режиме, или при загрузке данных, или при создании отчетов, или в целом ряде других, создайте какое-либо сообщение, указывающее, что процесс не удался. Если пользователи зависят от этих данных, а их там нет, это ваше приложение сломано, а не ожидания пользователей. Я понимаю, что вы переносите систему, но при этом вы не должны переносить очевидные ошибки. Это один.

1

Во-первых, избегайте подобных перехватов «любых исключений» без какого-либо конкретного поведения. За исключением очень простых функций, подумайте о том, чтобы зарегистрировать их где-нибудь или переписать код более элегантным образом.

Нашел тут: видимо, вообще ничего ставить не надо.

Вы должны попробовать следующее:

 ИСКЛЮЧЕНИЕ
  КОГДА ДРУГИЕ ТОГДА
  -- Ничего не делать
 

Надеюсь, это поможет.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *