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(), вона стає важливим інструментом для створення надійних, керованих і зрозумілих систем.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ