JavaRush /Курси /SQL SELF /Контроль виконання функцій: PERFORM

Контроль виконання функцій: PERFORM

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

PERFORM у світі PostgreSQL — це такий суворий мовчазний герой, який приходить, робить свою справу і зникає, не залишаючи після себе жодних слідів у вигляді повернутих даних. Ця команда використовується, коли ти хочеш виконати SQL-запит всередині функції PL/pgSQL, але тобі не треба обробляти чи зберігати результат. Основна задача PERFORM — викликати запит, щоб щось сталося, наприклад, модифікація даних чи виклик іншої функції, а не отримання результату.

PERFORM юзається в тих випадках, коли результат запиту нам не потрібен. На відміну від звичайного SELECT, який чекає, що ти щось з цим результатом зробиш, PERFORM просто запускає запит і мовчки йде далі. Це особливо зручно, якщо ти викликаєш функцію заради її дії, а не заради того, що вона поверне. Наприклад, щоб записати щось у лог. Такий підхід робить код простішим і зрозумілішим: менше зайвого, більше сенсу.

Приклади використання PERFORM

Виклик функцій

Давай розберемося з реальним прикладом. Уяви, що у нас є функція log_action, яка записує інфу про дії користувача в логи. Ця функція нічого не повертає, і ми просто хочемо, щоб вона спрацювала. Ось як це робиться з PERFORM:

CREATE OR REPLACE FUNCTION log_action(user_id INT, action TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO logs (user_id, action, log_time)
    VALUES (user_id, action, NOW());
END;
$$ LANGUAGE plpgsql;

-- Далі ми юзаємо PERFORM для виклику цієї функції:
PERFORM log_action(5, 'Користувач увійшов');

Що тут відбувається? Команда PERFORM викликає функцію log_action, яка додає запис у таблицю logs. Переконайся, що ти розумієш: результат виклику функції ігнорується. Ми юзаємо її виключно заради її ефекту, а не заради повернення значень.

Оновлення даних

Іноді PERFORM корисний, коли треба виконати запит для зміни даних без інтересу до його результату. Наприклад, оновимо статус замовлення в таблиці orders.

CREATE OR REPLACE FUNCTION update_order_status(order_id INT, new_status TEXT) RETURNS VOID AS $$
BEGIN
    UPDATE orders
    SET status = new_status
    WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;

-- Юзаємо PERFORM для виклику цієї функції:
PERFORM update_order_status(101, 'Відправлено');

Тут update_order_status оновлює статус замовлення з ідентифікатором 101. Ми не цікавимось результатом SQL-запиту всередині функції, тому PERFORM — ідеальний вибір.

Запуск допоміжних операцій

Іноді функції містять міні-операції, зведені до "допоміжної" логіки, яка допомагає завершити складний процес. Припустимо, ми хочемо скинути кеш після оновлення таблиці:

CREATE OR REPLACE FUNCTION clear_cache() RETURNS VOID AS $$
BEGIN
    DELETE FROM cache_table;
END;
$$ LANGUAGE plpgsql;

-- Викликаємо її в іншій функції:
CREATE OR REPLACE FUNCTION update_product(product_id INT, new_price NUMERIC) RETURNS VOID AS $$
BEGIN
    UPDATE products
    SET price = new_price
    WHERE id = product_id;

    -- Скидаємо кеш після зміни даних:
    PERFORM clear_cache();
END;
$$ LANGUAGE plpgsql;

Ось у чому магія: ти можеш послідовно виконувати дії, використовуючи PERFORM для виклику функцій, результат яких тобі взагалі не потрібен.

Практичні задачі

Давай розглянемо кілька прикладів того, як PERFORM може полегшити життя розробнику.

Приклад 1: логування виконання етапів процедури

Припустимо, у нас є складна процедура обробки платежів, і треба відслідковувати кожен її етап, записуючи це в лог. Ми можемо визначити функцію log_stage для запису інфи, а потім юзати PERFORM:

CREATE OR REPLACE FUNCTION log_stage(stage_name TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO process_logs(stage, log_time)
    VALUES (stage_name, NOW());
END;
$$ LANGUAGE plpgsql;

-- А ось приклад процедури:
CREATE OR REPLACE FUNCTION process_payment(payment_id INT) RETURNS VOID AS $$
BEGIN
    -- Логування початку
    PERFORM log_stage('Старт обробки платежу');

    -- Виконуємо перший етап
    UPDATE payments
    SET status = 'В обробці'
    WHERE id = payment_id;

    PERFORM log_stage('Оновлено статус платежу');

    -- Виконуємо фінальний етап
    UPDATE payments
    SET status = 'Завершено'
    WHERE id = payment_id;

    PERFORM log_stage('Платіж завершено');
END;
$$ LANGUAGE plpgsql;

Тут log_stage викликається через PERFORM для запису стану виконання на кожному етапі процедури. Це робить наш код легшим для дебагу.

Приклад 2: активація сповіщень

Уяви, що у тебе є система сповіщень, і треба відправляти сповіщення після кожної важливої дії. PERFORM можна юзати для виклику функції, яка за це відповідає:

CREATE OR REPLACE FUNCTION send_notification(user_id INT, message TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO notifications (user_id, message, created_at)
    VALUES (user_id, message, NOW());
END;
$$ LANGUAGE plpgsql;

-- Юзаємо в процедурі:
CREATE OR REPLACE FUNCTION complete_task(task_id INT) RETURNS VOID AS $$
DECLARE
    user_id INT;
BEGIN
    -- Отримуємо автора задачі
    SELECT assigned_to INTO user_id
    FROM tasks
    WHERE id = task_id;

    -- Завершуємо задачу
    UPDATE tasks
    SET status = 'Завершено'
    WHERE id = task_id;

    -- Відправляємо сповіщення
    PERFORM send_notification(user_id, 'Твою задачу виконано');
END;
$$ LANGUAGE plpgsql;

Тут PERFORM дозволяє зосередитись тільки на побічному ефекті — відправці сповіщення, ігноруючи результат виконання функції.

Корисні поради і типові граблі

Коли ти юзаєш PERFORM, важливо пам’ятати про деякі особливості. Наприклад, PERFORM не перевіряє, що запит повернув дані. Це означає, що якщо результат функції чи SQL-запиту важливий для логіки виконання, краще юзати SELECT INTO. Дивись приклад:

-- Потенційна помилка
PERFORM якась_функція_яка_має_повернути_значення();

-- Фікс
SELECT якась_функція_яка_має_повернути_значення() INTO якась_змінна;

Ще одна часта грабля — використання PERFORM там, де логічно треба отримати результат запиту, наприклад, валідація даних. У таких випадках, звісно, краще отримувати результат і перевіряти його.

У реальних проектах команда PERFORM допомагає робити функції і процедури простішими, легшими для читання і дебагу. У поєднанні з логуванням (RAISE NOTICE) і вбудованими діагностичними функціями PostgreSQL, такими як current_query(), вона стає важливим інструментом для створення надійних, керованих і зрозумілих систем.

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