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, 'User logged in');

Что здесь происходит? Команда 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, 'Shipped');

Здесь 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('Start payment processing');

    -- Выполняем первый этап
    UPDATE payments
    SET status = 'Processing'
    WHERE id = payment_id;

    PERFORM log_stage('Updated payment status');

    -- Выполняем финальный этап
    UPDATE payments
    SET status = 'Completed'
    WHERE id = payment_id;

    PERFORM log_stage('Payment completed');
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 = 'Completed'
    WHERE id = task_id;

    -- Отправляем уведомление
    PERFORM send_notification(user_id, 'Your task has been completed');
END;
$$ LANGUAGE plpgsql;

Здесь PERFORM позволяет сосредоточить внимание только на побочном эффекте — отправке уведомления, игнорируя результат выполнения функции.

Полезные советы и типичные ошибки

Когда вы используете PERFORM, важно помнить о некоторых особенностях. Например, PERFORM не проверяет, что запрос вернул данные. Это значит, что если результат функции или SQL-запроса важен для логики выполнения, лучше использовать SELECT INTO. Рассмотрим пример:

-- Потенциальная ошибка
PERFORM some_function_that_must_return_value();

-- Исправление
SELECT some_function_that_must_return_value() INTO some_variable;

Ещё одна частая ошибка — использование PERFORM там, где логически необходимо получить результат запроса, например, валидация данных. В таких случаях, конечно, лучше получать результат и проверять его.

В реальных проектах команда PERFORM помогает делать функции и процедуры проще, легче для чтения и отладки. В сочетании с логированием (RAISE NOTICE) и встроенными диагностическими функциями PostgreSQL, такими как current_query(), она становится важным инструментом для создания надёжных, управляемых и понятных систем.

2
Задача
SQL SELF, 55 уровень, 3 лекция
Недоступна
Вызов логирующей функции с использованием `PERFORM`
Вызов логирующей функции с использованием `PERFORM`
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Ra Уровень 35 Student
21 августа 2025
👎