JavaRush /Курси /SQL SELF /Логування помилок: рівні логування та формат повідомлень

Логування помилок: рівні логування та формат повідомлень

SQL SELF
Рівень 55 , Лекція 2
Відкрита

Ми з тобою зараз як секретні агенти — наші функції та процедури виконують місії: обробляють дані, роблять обчислення або просто творять магію всередині бази. Але як дізнатися, якщо щось піде не так? Як зрозуміти, на якому етапі зламалась "масажна ванночка для даних"? Тут на допомогу приходять логування та обробка помилок.

Пам’ятаєш, ми вже починали знайомитись із тим, як у PostgreSQL та PL/pgSQL можна "спілкуватися" і вести логи:

  • RAISE NOTICE: спокійний, дружній тон — "Гей, тут все ок, але, може, захочеш глянути на це".
  • RAISE WARNING: тон трохи гучніше — "Ой, тут щось дивне, може, зазирни".
  • RAISE EXCEPTION: панічна сирена — "СТОП! Алгоритм у біді! Ми зупинили виконання, щоб все не пішло шкереберть".

Кожен із цих рівнів має своє призначення, і важливо правильно обирати, який із них використовувати.

Ось як ці повідомлення виглядають у коді:

DO $$
BEGIN
    -- Рівень NOTICE (все нормально, просто повідомлення)
    RAISE NOTICE 'Просто повідомлення: почалась обробка даних';

    -- Рівень WARNING (щось підозріле)
    RAISE WARNING 'Попередження: формат даних у стовпці може бути некоректним';

    -- Рівень EXCEPTION (критична помилка)
    RAISE EXCEPTION 'Помилка: вхідне значення недопустиме!';
END $$;

Коли використовувати:

  • RAISE NOTICE — для відладки та спокійного виводу інформації.
  • RAISE WARNING — щоб попередити про потенційно некоректні дані.
  • RAISE EXCEPTION — коли трапляються критичні помилки, через які виконання функції треба зупинити.

Обробка помилок з RAISE EXCEPTION

RAISE EXCEPTION — це твій стоп-кран. Якщо щось іде не так, ти зможеш зупинити виконання функції й повідомити про помилку.

Нагадаю, базове використання виглядає так:

RAISE EXCEPTION 'Твоє повідомлення про помилку';

Але щоб зробити повідомлення більш інформативними, можна використовувати змінні:

DECLARE
    input_value INTEGER;
BEGIN
    input_value := NULL;

    IF input_value IS NULL THEN
        RAISE EXCEPTION 'Помилка: вхідне значення NULL. Очікувалось значення INTEGER';
    END IF;
END;

Форматування повідомлень

Ти можеш підставляти змінні прямо в текст повідомлення:

DECLARE
    var1 TEXT := 'Дані';
    var2 INTEGER := 42;
BEGIN
    RAISE EXCEPTION 'Помилка при обробці % з ID %', var1, var2;
END;

Вивід: Помилка при обробці Дані з ID 42.

Приклад: валідація даних

Уяви, що у тебе є процедура, яка приймає вік людини. Якщо вік від’ємний, логічно викликати помилку:

CREATE OR REPLACE FUNCTION validate_age(age INTEGER)
RETURNS VOID AS $$
BEGIN
    IF age < 0 THEN
        RAISE EXCEPTION 'Вік не може бути від’ємним: %', age;
    END IF;
END;
$$ LANGUAGE plpgsql;

-- Виклик функції
SELECT validate_age(-5);  -- Викличе помилку

Інформування з RAISE NOTICE

Якщо RAISE EXCEPTION — це сирена, то RAISE NOTICE — це дружнє поплескування по плечу. За допомогою цього рівня можна додавати коментарі для розуміння того, що відбувається всередині функції.

Коли використовувати RAISE NOTICE:

  • Вивід відладочної інформації (наприклад, поточний стан змінних).
  • Повідомлення про початок виконання етапу або результат обчислень.

Приклад: інформаційні повідомлення

CREATE OR REPLACE FUNCTION calculate_discount(price NUMERIC, discount_rate NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
    final_price NUMERIC;
BEGIN
    RAISE NOTICE 'Ціна перед знижкою: %', price;
    RAISE NOTICE 'Ставка знижки: %', discount_rate;

    final_price := price - (price * discount_rate);

    RAISE NOTICE 'Підсумкова ціна: %', final_price;

    RETURN final_price;
END;
$$ LANGUAGE plpgsql;

-- Виклик функції
SELECT calculate_discount(100, 0.2);
-- Виведе:
-- NOTICE: Ціна перед знижкою: 100
-- NOTICE: Ставка знижки: 0.2
-- NOTICE: Підсумкова ціна: 80

Практичне застосування: планування та логування

Припустимо, у тебе є складна процедура обробки даних, і ти хочеш знати, на якому етапі вона зараз знаходиться:

CREATE OR REPLACE FUNCTION process_data_step_by_step()
RETURNS VOID AS $$
BEGIN
    RAISE NOTICE 'Крок 1: Підготовка даних';
    -- Твоя логіка для першого етапу

    RAISE NOTICE 'Крок 2: Валідація даних';
    -- Твоя логіка для другого етапу

    RAISE NOTICE 'Крок 3: Збереження даних';
    -- Твоя логіка для третього етапу
END;
$$ LANGUAGE plpgsql;

-- Виклик функції
SELECT process_data_step_by_step();
-- У логах відобразиться покрокове виконання

Наведемо ще один приклад. Давай уявимо магазин, який пропонує знижки тільки для замовлень вище певної суми:

CREATE OR REPLACE FUNCTION apply_discount(order_amount NUMERIC)
RETURNS NUMERIC AS $$
BEGIN
    IF order_amount < 50 THEN
        RAISE EXCEPTION 'Помилка: сума замовлення має бути не менше 50, поточна сума: %', order_amount;
    END IF;

    RETURN order_amount * 0.9;  -- Застосовуємо 10% знижку
END;
$$ LANGUAGE plpgsql;

-- Виклик функції
SELECT apply_discount(30);  -- Помилка: сума замовлення має бути не менше 50

Типові помилки

Помилка 1: логування повідомлень без параметрів.

Виглядає неінформативно, особливо у великих процедурах:

RAISE NOTICE 'Сталася помилка';  -- Чому? Де? Як?

Рекомендація: завжди додавай контекст:

RAISE NOTICE 'Помилка у функції process_data(): вхідне значення: %', input_value;

Помилка 2: використання RAISE EXCEPTION там, де достатньо RAISE WARNING.

Якщо ти перестараєшся з виключеннями, код буде перериватися з будь-якого приводу, що ускладнить обробку даних.

Порада: використовуй рівні логування свідомо. Для відладки обирай NOTICE, а для критичних моментів — EXCEPTION.

Помилка 3: відсутність логування взагалі.

Це як шукати ключі у темній кімнаті. Без логів відладка складних процесів стає майже неможливою.

Порада: додавай RAISE NOTICE на ключових етапах виконання функції, особливо якщо вона велика і складна.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ