Gymterview
middle

Чем отличаются функции от процедур в PostgreSQL?

Начиная с PostgreSQL 11 поддерживаются как функции (FUNCTION), так и процедуры (PROCEDURE). Ключевое различие: процедуры могут управлять транзакциями (COMMIT/ROLLBACK внутри тела), а функции — нет.

Функции (FUNCTION)

Пример
CREATE OR REPLACE FUNCTION get_account_balance(p_account_id bigint)
RETURNS numeric AS $$
DECLARE
    v_balance numeric;
BEGIN
    SELECT balance INTO v_balance
    FROM accounts WHERE id = p_account_id;

    IF NOT FOUND THEN
        RAISE EXCEPTION 'Счёт % не найден', p_account_id;
    END IF;

    RETURN v_balance;
END;
$$ LANGUAGE plpgsql;

SELECT get_account_balance(1);

Процедуры (PROCEDURE)

Пример процедуры перевода средств
CREATE OR REPLACE PROCEDURE transfer_funds(
    p_from_account bigint,
    p_to_account bigint,
    p_amount numeric
)
LANGUAGE plpgsql AS $$
BEGIN
    IF p_amount <= 0 THEN
        RAISE EXCEPTION 'Сумма перевода должна быть положительной';
    END IF;

    UPDATE accounts SET balance = balance - p_amount WHERE id = p_from_account;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Счёт-отправитель % не найден', p_from_account;
    END IF;

    UPDATE accounts SET balance = balance + p_amount WHERE id = p_to_account;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'Счёт-получатель % не найден', p_to_account;
    END IF;

    -- Процедура может управлять транзакциями!
    COMMIT;
END;
$$;

CALL transfer_funds(1, 2, 50000);

Ключевые отличия

Свойство FUNCTION PROCEDURE
Возвращает значение Да (RETURNS) Нет
Управление транзакциями Нет (COMMIT/ROLLBACK запрещены) Да (COMMIT/ROLLBACK разрешены)
Использование в SELECT SELECT func() Нет
Вызов SELECT func() или в выражениях CALL proc()
Используется в триггерах Да Нет

Процедуры полезны для длительных пакетных операций, где нужно промежуточно фиксировать результаты (например, миграция данных большими батчами).

На собеседовании: единственный критический факт — процедуры могут делать COMMIT/ROLLBACK, функции — нет. Это определяет выбор: если нужно промежуточно фиксировать результаты в длительной операции — процедура, если нужно вернуть значение или использовать в SELECT — функция.