JavaRush /Курси /SQL SELF /Розбір типових помилок при створенні функцій

Розбір типових помилок при створенні функцій

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

Сьогодні ми розберемо типові помилки при створенні функцій, їх причини та способи усунення. Бо тільки через дебаг справжній майстер пізнає своє ремесло — кодинг! Let's debug it!

Створення функцій, особливо на початку вивчення PL/pgSQL, може здатися складним завданням. Навіть найдосвідченіші розробники в PostgreSQL натрапляють на підводні камені. Давай розберемо їх по черзі.

1. Пропуск ключового слова RETURNS

PL/pgSQL дуже суворий до того, як ти описуєш функції. Одна з найпоширеніших помилок — забути вказати тип даних, який має повертати функція. Дивись приклад:

-- Помилка: відсутнє ключове слово RETURNS
CREATE FUNCTION incorrect_function() AS $$
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

PostgreSQL не зможе зрозуміти, що саме має повертати ця функція. RETURNS — обов'язковий елемент синтаксису, який описує тип повертаємих даних (наприклад, RETURNS INT, RETURNS TEXT або навіть RETURNS VOID).

Виправлення: додай ключове слово RETURNS з вказанням типу даних:

CREATE FUNCTION correct_function() RETURNS INT AS $$
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

2. Повернення результату без RETURN

Початківці часто забувають, що в PL/pgSQL, щоб повернути результат, треба явно використовувати оператор RETURN. Ось приклад:

-- Помилка: відсутній RETURN
CREATE FUNCTION missing_return() RETURNS TEXT AS $$
BEGIN
    'Привіт, Світ!'; -- Просто рядок, але не повернутий
END;
$$ LANGUAGE plpgsql;

Тут рядок 'Привіт, Світ!' просто вказаний, але не повертається. PostgreSQL сприйме це як недосягнутий результат і видасть помилку.

Виправлення: додай явний оператор RETURN:

CREATE FUNCTION fixed_return() RETURNS TEXT AS $$
BEGIN
    RETURN 'Привіт, Світ!';
END;
$$ LANGUAGE plpgsql;

3. Спроба записати дані в неоголошену змінну

У PL/pgSQL перед використанням змінну треба оголосити в блоці DECLARE. Наприклад:

-- Помилка: змінна my_var не оголошена
CREATE FUNCTION missing_variable() RETURNS VOID AS $$
BEGIN
    my_var := 'Привіт, Світ!';
END;
$$ LANGUAGE plpgsql;

PostgreSQL не знає про існування змінної my_var, бо вона не була оголошена в блоці DECLARE.

Виправлення: завжди оголошуй змінні в DECLARE:

CREATE FUNCTION declared_variable() RETURNS VOID AS $$
DECLARE
    my_var TEXT;
BEGIN
    my_var := 'Привіт, Світ!';
END;
$$ LANGUAGE plpgsql;

4. Неправильне використання типу повернення VOID

Тип VOID означає, що функція нічого не повертає. Іноді розробники намагаються використати RETURN у функціях з типом VOID, що призводить до помилок:

-- Помилка: RETURN у функції з VOID
CREATE FUNCTION void_example() RETURNS VOID AS $$
BEGIN
    RETURN 1; -- Повернення значення недопустиме
END;
$$ LANGUAGE plpgsql;

Функції з типом повернення VOID не мають повертати значення. Оператор RETURN можна використовувати, але без значення.

Виправлення: або видали RETURN, або залиш його без значення:

CREATE FUNCTION correct_void() RETURNS VOID AS $$
BEGIN
    -- Просто виконуємо дії
    RAISE NOTICE 'Ця функція нічого не повертає';
    RETURN; -- Завершення функції
END;
$$ LANGUAGE plpgsql;

5. Неправильне використання RAISE для дебагу

Дебаг у PL/pgSQL часто роблять через оператор RAISE NOTICE. Але неправильні формати і змінні можуть призвести до помилок.

Приклад:

-- Помилка: неправильний формат
CREATE FUNCTION debug_example() RETURNS VOID AS $$
BEGIN
    RAISE NOTICE 'Значення: %'; -- Пропущена змінна
END;
$$ LANGUAGE plpgsql;

Оператор RAISE очікує, що після % буде змінна або значення. Якщо залишити % без нічого, PostgreSQL не зможе обробити команду.

Виправлення: переконайся, що змінні або значення вказані коректно:

CREATE FUNCTION fixed_debug() RETURNS VOID AS $$
DECLARE
    my_var TEXT := 'PostgreSQL';
BEGIN
    RAISE NOTICE 'Значення: %', my_var; -- Вказана змінна
END;
$$ LANGUAGE plpgsql;

6. Проблеми з іменами змінних і стовпців

Якщо ім'я змінної збігається з ім'ям стовпця, це може призвести до неочікуваних результатів. Наприклад:

-- Помилка: конфлікт імен змінної і стовпця
CREATE FUNCTION name_conflict() RETURNS TEXT AS $$
DECLARE
    name TEXT;
BEGIN
    SELECT name INTO name FROM students LIMIT 1; -- Яке name використовується?
    RETURN name;
END;
$$ LANGUAGE plpgsql;

PL/pgSQL віддає перевагу змінним перед іменами стовпців, якщо вони збігаються.

Виправлення: використовуй псевдоніми для таблиць або уникай збігів.

CREATE FUNCTION fixed_conflict() RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    SELECT s.name INTO student_name FROM students s LIMIT 1;
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

7. Некоректне виконання запитів у циклі

Помилки часто трапляються при спробі виконати SQL-запити всередині циклів. Наприклад:

-- Помилка: некоректний запит у циклі
CREATE FUNCTION cycle_error() RETURNS VOID AS $$
BEGIN
    FOR rec IN SELECT * FROM students LOOP
        EXECUTE 'UPDATE students SET active = TRUE WHERE id = ' || rec.id;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

SQL-інʼєкції... Небезпека! Конкатенація рядків для SQL-запитів — погана практика. Це може призвести до вразливості.

Щоб виправити, використовуй параметри:

CREATE FUNCTION safe_cycle() RETURNS VOID AS $$
BEGIN
    FOR rec IN SELECT * FROM students LOOP
        EXECUTE 'UPDATE students SET active = TRUE WHERE id = $1' USING rec.id;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

8. Помилки з типами даних

Приклад помилки:

-- Помилка: невідповідність типів даних
CREATE FUNCTION type_error() RETURNS INT AS $$
DECLARE
    my_var TEXT := 'not_a_number';
BEGIN
    RETURN my_var; -- Помилка при поверненні тексту замість INT
END;
$$ LANGUAGE plpgsql;

PostgreSQL очікує INT, але отримує TEXT. Відповідність типів даних суворо контролюється.

Як виправити? Переконайся, що типи даних збігаються, або зроби явне перетворення:

CREATE FUNCTION type_correct() RETURNS INT AS $$
DECLARE
    my_var TEXT := '42';
BEGIN
    RETURN my_var::INT; -- Перетворення тексту в число
END;
$$ LANGUAGE plpgsql;

Кращі практики та поради

  • Діли складні функції на менші. Це спростить дебаг і тестування.
  • Використовуй коментарі всередині функцій для опису складних операцій.
  • Завжди тестуй функції на малих даних перед використанням на реальних таблицях.
  • Дебаж через RAISE NOTICE, щоб зрозуміти хід виконання.
  • Уникай SQL-інʼєкцій: використовуй параметри для запитів.
-- Використання RAISE для дебагу
DO $$
DECLARE
    total_students INT;
BEGIN
    SELECT COUNT(*) INTO total_students FROM students;
    RAISE NOTICE 'Всього студентів: %', total_students; -- Дебажне повідомлення
END;
$$;

Ці поради допоможуть уникнути купи головного болю і назавжди знищити "граблі" PL/pgSQL!

1
Опитування
Створення простих функцій, рівень 50, лекція 4
Недоступний
Створення простих функцій
Створення простих функцій
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ