Переходячи до основної теми, давай зупинимось на найбільш поширених помилках і недоліках, з якими ти можеш зіткнутися. Бо помилки в SQL — це біль будь-якого розробника, і, як на зло, вони трапляються у найневдаліший момент.
1. Помилки синтаксису: "забув закрити IF"
Синтаксичні помилки — це найпростіші проблеми, але вони трапляються частіше, ніж здається. Наприклад, якщо ти забув закрити умовний блок IF за допомогою END IF;, компілятор одразу тебе засудить.
Приклад помилки:
CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
IF num > 0 THEN
RETURN 'Позитивне';
ELSE
RETURN 'Негативне';
-- десь загубився END IF;
END;
$$ LANGUAGE plpgsql;
При спробі виконати цей код ти отримаєш помилку: ERROR: syntax error at or near "END". Чому? Бо блок IF залишився відкритим.
Як уникнути таких помилок?
Завжди використовуй чітку структуру коду. Коли відкриваєш блок (наприклад, IF), одразу пиши його закриття. Ось виправлений приклад:
CREATE OR REPLACE FUNCTION check_number(num INTEGER)
RETURNS TEXT AS $$
BEGIN
IF num > 0 THEN
RETURN 'Позитивне';
ELSE
RETURN 'Негативне';
END IF; -- не забудь закрити блок
END;
$$ LANGUAGE plpgsql;
2. Забута обробка всіх умов у CASE: "А що, якщо я нікуди не попаду?"
Коли ти використовуєш CASE, завжди додавай гілку ELSE для обробки неочікуваної поведінки. Відсутність цієї гілки може призвести до небажаного повернення NULL.
Приклад помилки:
CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
RETURN CASE grade
WHEN 'A' THEN 'Відмінно'
WHEN 'B' THEN 'Добре'
WHEN 'C' THEN 'Середньо'
-- А що, якщо grade = 'D' або інша оцінка?
END;
END;
$$ LANGUAGE plpgsql;
Якщо ти передаси значення D, функція поверне NULL, що може викликати проблеми у твоєму коді.
Виправлений варіант:
CREATE OR REPLACE FUNCTION grade_result(grade CHAR)
RETURNS TEXT AS $$
BEGIN
RETURN CASE grade
WHEN 'A' THEN 'Відмінно'
WHEN 'B' THEN 'Добре'
WHEN 'C' THEN 'Середньо'
ELSE 'Невідома оцінка' -- Перехоплюємо всі інші випадки
END;
END;
$$ LANGUAGE plpgsql;
3. Проблеми з нескінченними циклами: "Чому сервер завис?"
Використовуючи цикл LOOP, легко забути додати умову для виходу з циклу. Це може призвести до нескінченного виконання:
Приклад помилки:
CREATE OR REPLACE FUNCTION infinite_loop_demo()
RETURNS VOID AS $$
DECLARE
i INTEGER := 1;
BEGIN
LOOP
i := i + 1;
-- Немає умови для виходу!
END LOOP;
END;
$$ LANGUAGE plpgsql;
Цей код призведе до зависання сервера, бо цикл ніколи не завершиться.
Як виправити:
Додай умову виходу за допомогою EXIT:
CREATE OR REPLACE FUNCTION finite_loop_demo()
RETURNS VOID AS $$
DECLARE
i INTEGER := 1;
BEGIN
LOOP
i := i + 1;
IF i > 10 THEN
EXIT; -- Умова виходу
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;
4. Пропуск ітерацій у циклах: "А що з відсутніми даними?"
При використанні CONTINUE для пропуску ітерацій може виникнути помилка, якщо ти не врахував всі варіанти поведінки. Наприклад:
Приклад помилки:
CREATE OR REPLACE FUNCTION skip_even()
RETURNS VOID AS $$
DECLARE
i INTEGER := 0;
BEGIN
WHILE i < 10 LOOP
i := i + 1;
IF i % 2 = 0 THEN
CONTINUE; -- Просто пропускаємо парні значення
END IF;
RAISE NOTICE 'Непарне число: %', i;
END LOOP;
END;
$$ LANGUAGE plpgsql;
А що, якщо всі числа будуть парними? Сервер працюватиме, але результату ти не побачиш.
Як виправити:
Переконайся, що ти обробляєш всі дані коректно, і додавай логи для контролю:
CREATE OR REPLACE FUNCTION skip_even_logging()
RETURNS VOID AS $$
DECLARE
i INTEGER := 0;
BEGIN
WHILE i < 10 LOOP
i := i + 1;
IF i % 2 = 0 THEN
RAISE NOTICE 'Пропускаємо парне число: %', i;
CONTINUE;
END IF;
RAISE NOTICE 'Непарне число: %', i;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Тепер ти бачиш, які числа були пропущені.
5. Некоректна обробка помилок: "Де мій RAISE EXCEPTION?"
Обробка помилок через RAISE EXCEPTION — потужний інструмент, але його легко зламати неправильним використанням.
Приклад помилки:
CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
IF num < 0 THEN
RAISE 'Негативне число не дозволено!';
END IF;
RETURN num * num;
END;
$$ LANGUAGE plpgsql;
Цей код викличе помилку, бо синтаксис RAISE невірний (немає рівня повідомлення).
Виправлений варіант:
CREATE OR REPLACE FUNCTION calculate_square(num INTEGER)
RETURNS INTEGER AS $$
BEGIN
IF num < 0 THEN
RAISE EXCEPTION 'Негативне число не дозволено!';
END IF;
RETURN num * num;
END;
$$ LANGUAGE plpgsql;
6. Помилки при логуванні: "Чому мої помилки не пишуться в error_log?"
Некоректний запис у таблицю error_log може виникнути через помилки у запитах INSERT INTO.
Приклад помилки:
CREATE OR REPLACE FUNCTION log_error(err_msg TEXT)
RETURNS VOID AS $$
BEGIN
INSERT INTO error_log (error_message, error_time)
VALUES (err_msg, CURRENT_TIMESTAMP); -- А якщо помилка у стовпцях?
END;
$$ LANGUAGE plpgsql;
Якщо у таблиці error_log було змінено ім'я стовпця (наприклад, на error_msg), це викличе помилку.
Як уникнути:
Завжди перевіряй структуру таблиці або використовуй сувору схему для керування даними.
7. Загальна неуважність і "людський фактор"
Помилки бувають не лише технічними, а й пов'язаними з неуважністю. Забута відладка, невикористані змінні чи відсутність форматування коду можуть перетворити твою функцію на кашу.
Приклад:
DECLARE
i INTEGER; -- Навіщо, якщо змінна не використовується?
Виправлення: видаляй зайві частини коду, щоб він залишався чистим і зрозумілим.
Тепер ти готовий уникати найпоширеніших помилок у PL/pgSQL і писати код, який приносить більше радості, ніж болю. Не забувай тестувати, логувати і вчасно фіксити баги — цим ти зекономиш собі купу нервів і дзвінків від клієнтів!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ