Перехват исключений (Catching Exceptions) в PL/pgSQL
В этом шаге вы узнаете, как перехватывать исключения (exceptions) в PL/pgSQL с помощью блока EXCEPTION
. Обработка исключений позволяет вам корректно обрабатывать ошибки, предотвращая сбой вашей функции и предоставляя информативные сообщения об ошибках.
Основная структура блока обработки исключений выглядит следующим образом:
BEGIN
-- Code that might raise an exception
EXCEPTION
WHEN exception_name THEN
-- Code to handle the exception
END;
Ключевые слова BEGIN
и END
определяют блок кода, в котором могут возникать исключения. Ключевое слово EXCEPTION
вводит раздел обработки исключений. Предложение WHEN
указывает тип исключения для перехвата, и код, следующий за THEN
, выполняется при возникновении этого исключения.
Давайте создадим функцию, которая пытается разделить число на ноль и перехватывает возникающее исключение. Мы назовем ее safe_divide
.
CREATE OR REPLACE FUNCTION safe_divide(numerator INTEGER, denominator INTEGER)
RETURNS INTEGER AS $$
BEGIN
RETURN numerator / denominator;
EXCEPTION
WHEN division_by_zero THEN
RAISE NOTICE 'Division by zero occurred!';
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
Эта функция принимает два целочисленных аргумента: numerator
(числитель) и denominator
(знаменатель). Внутри блока BEGIN
она пытается разделить numerator
на denominator
. Если denominator
равен нулю, будет вызвано исключение division_by_zero
(деление на ноль). Блок EXCEPTION
перехватывает это исключение, выводит уведомление и возвращает NULL
.
Теперь давайте вызовем функцию с делителем, равным нулю:
SELECT safe_divide(10, 0);
Вы должны увидеть вывод, подобный этому:
NOTICE: Division by zero occurred!
safe_divide
-------------
NULL
(1 row)
Сообщение NOTICE
"Division by zero occurred!" отображается, и функция возвращает NULL
, указывая, что исключение было перехвачено и обработано.
Теперь давайте вызовем функцию с допустимыми входными данными:
SELECT safe_divide(10, 2);
Вы должны увидеть вывод, подобный этому:
safe_divide
-------------
5
(1 row)
Функция возвращает правильное частное, 5, без вызова каких-либо исключений.
Вы также можете перехватывать другие типы исключений, такие как numeric_value_out_of_range
(числовое значение вне диапазона), null_value_not_allowed
(недопустимое нулевое значение) и others
(другие). Обработчик исключений others
перехватывает любое исключение, которое не обрабатывается явно предыдущим предложением WHEN
.
Давайте изменим функцию, чтобы перехватывать любое исключение и возвращать -1:
CREATE OR REPLACE FUNCTION safe_divide(numerator INTEGER, denominator INTEGER)
RETURNS INTEGER AS $$
BEGIN
RETURN numerator / denominator;
EXCEPTION
WHEN division_by_zero THEN
RAISE NOTICE 'Division by zero occurred!';
RETURN NULL;
WHEN OTHERS THEN
RAISE NOTICE 'An unexpected error occurred: %', SQLERRM;
RETURN -1;
END;
$$ LANGUAGE plpgsql;
В этой измененной функции, если возникает какое-либо исключение, отличное от division_by_zero
, будет выполнен обработчик исключений OTHERS
. SQLERRM
— это встроенная переменная, которая содержит сообщение об ошибке, связанное с исключением.