JavaRush /Курсы /SQL SELF /Взаимодействие между функциями и процедурами

Взаимодействие между функциями и процедурами

SQL SELF
55 уровень , 1 лекция
Открыта

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

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

Функции vs Процедуры: в чем разница?

Давайте вспомним, чем функции отличаются от процедур в PostgreSQL:

  • Функции (FUNCTION):

    • Возвращают значения.
    • Их можно использовать в SELECT.
    • Часто применяются для вычислений или преобразования данных.
  • Процедуры (PROCEDURE):

    • Не возвращают значений напрямую.
    • Используются для выполнения операций, таких как вставка, обновление или удаление данных.
    • Вызываются с помощью команды CALL.

Передача данных между функциями

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

Вот как выглядит вызов функции внутри другой функции:

CREATE OR REPLACE FUNCTION get_student_name(student_id INT)
RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    -- Извлекаем имя студента по его ID
    SELECT name INTO student_name FROM students WHERE id = student_id;

    -- Возвращаем имя
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

Эту функцию можно вызывать из другой функции:

CREATE OR REPLACE FUNCTION welcome_student(student_id INT)
RETURNS TEXT AS $$
DECLARE
    message TEXT;
BEGIN
    -- Получаем имя студента с помощью другой функции
    message := 'Welcome, ' || get_student_name(student_id) || '!';

    -- Возвращаем приветствие
    RETURN message;
END;
$$ LANGUAGE plpgsql;
  1. Функция get_student_name возвращает имя студента по его идентификатору (student_id).
  2. В другой функции — welcome_student — это имя используется для создания приветственного сообщения.

Примечание: Извлечение данных через SELECT INTO сохраняет результат запроса в переменной PL/pgSQL.

Пример вызова процедур из функций

Теперь давайте рассмотрим, как вызывать процедуру из функции. Предположим, у нас есть процедура, которая фиксирует время входа студента в систему:

CREATE OR REPLACE PROCEDURE log_student_entry(student_id INT)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO log_entries(student_id, entry_time)
    VALUES (student_id, NOW());
END;
$$;

Теперь вызовем эту процедуру из функции, где она будет фиксировать вход и возвращать сообщение:

CREATE OR REPLACE FUNCTION student_login(student_id INT)
RETURNS TEXT AS $$
BEGIN
    -- Вызываем процедуру для логирования
    CALL log_student_entry(student_id);

    -- Возвращаем сообщение
    RETURN 'Student login logged successfully.';
END;
$$ LANGUAGE plpgsql;

Практические примеры взаимодействия

Пример 1: расчёт итоговой суммы и логирование заказа

Представьте, что вы работаете с системой онлайн-заказов. Для расчёта итоговой суммы заказа у вас есть функция:

CREATE OR REPLACE FUNCTION calculate_order_total(order_id INT)
RETURNS NUMERIC AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Суммируем все позиции заказа
    SELECT SUM(price * quantity) INTO total
    FROM order_items
    WHERE order_id = order_id;

    RETURN total;
END;
$$ LANGUAGE plpgsql;

Для сохранения итоговой суммы заказа используется процедура:

CREATE OR REPLACE PROCEDURE log_order_total(order_id INT, total NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO order_totals(order_id, total)
    VALUES (order_id, total);
END;
$$;

Теперь свяжем их вместе:

CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS TEXT AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Вызываем функцию для расчета итоговой суммы
    total := calculate_order_total(order_id);

    -- Логируем итоговую сумму через процедуру
    CALL log_order_total(order_id, total);

    RETURN 'Order processed successfully.';
END;
$$ LANGUAGE plpgsql;

Пример 2: получение максимального рейтинга студента и обновление профиля

Функция для получения максимального рейтинга:

CREATE OR REPLACE FUNCTION get_highest_rating(student_id INT)
RETURNS INT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Находим максимальный рейтинг студента
    SELECT MAX(rating) INTO max_rating
    FROM ratings
    WHERE student_id = student_id;

    RETURN max_rating;
END;
$$ LANGUAGE plpgsql;

Процедура для обновления профиля студента:

CREATE OR REPLACE PROCEDURE update_student_profile(student_id INT, max_rating INT)
LANGUAGE plpgsql
AS $$
BEGIN
    UPDATE students
    SET highest_rating = max_rating
    WHERE id = student_id;
END;
$$;

Функция для вызова этих операций:

CREATE OR REPLACE FUNCTION refresh_student_profile(student_id INT)
RETURNS TEXT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Получаем максимальный рейтинг
    max_rating := get_highest_rating(student_id);

    -- Обновляем профиль студента
    CALL update_student_profile(student_id, max_rating);

    RETURN 'Profile updated successfully.';
END;
$$ LANGUAGE plpgsql;

Типичные ошибки при взаимодействии

Одна из самых распространённых ошибок — несоответствие типов данных между функцией и процедурой. Например, если ваша процедура ожидает параметр типа NUMERIC, а вы передаете INTEGER, PostgreSQL сообщит о несоответствии типов. Всегда проверяйте, что типы данных совпадают.

Еще одна ошибка заключается в циклическом вызове функций, когда функция A вызывает функцию B, а та, в свою очередь, снова вызывает A. Это приводит к бесконечному вызову и краху системы.

Практическая значимость

Зачем нам нужно такое взаимодействие? В реальной жизни функции и процедуры работают как "строительные блоки" сложных систем. Они позволяют разбить код на независимые части, что облегчает отладку, повторное использование и тестирование. Например:

  • На собеседовании вас могут попросить написать функцию, которая вызывает процедуру для выполнения сложной операции. Демонстрация практических навыков взаимодействия будет большим плюсом.
  • При разработке реальных приложений, таких как интернет-магазины, системы логирования или CRM, умение правильно организовать функциональность через взаимодействие функций и процедур значительно упрощает код.

Для дальнейшего изучения взаимодействия функций и процедур вы можете изучить официальную документацию по PL/pgSQL.

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