← К оглавлению занятия

💻 Примеры

📁 Блок: SQL / MySQL / Хранимые процедуры ⏱️ Время изучения: ~90 мин 🎯 Сложность: Продвинутая

⚡ Кратко: 💻 примеры

Параметры процедуры позволяют передавать данные в процедуру и получать результат обратно.

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

OUT используется для результата: процедура записывает значение в переменную вызывающего кода через SELECT ... INTO или SET.

INOUT совмещает оба направления: начальное значение приходит в процедуру, изменённое значение возвращается наружу.

Для OUT и INOUT в MySQL обычно передают пользовательские переменные вида @salary.

Минимальный пример: CALL get_employee_salary(1, @salary); SELECT @salary;.

Топ-3 ошибки: вызвать процедуру без CALL, передать литерал вместо переменной в OUT, забыть присвоить значение выходному параметру внутри процедуры.

Подготовка таблиц

Практическая часть источника использует таблицы products и employees. Ниже минимальный набор данных для локальной проверки.

DROP TABLE IF EXISTS products;
CREATE TABLE products (
    id INT PRIMARY KEY,
    product_name VARCHAR(100),
    price DECIMAL(10, 2)
);

INSERT INTO products (id, product_name, price) VALUES
    (1, 'Keyboard', 49.90),
    (2, 'Mouse', 19.90),
    (3, 'Monitor', 199.00);

DROP TABLE IF EXISTS employees;
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    monthly_salary INT
);

INSERT INTO employees (id, name, monthly_salary) VALUES
    (1, 'Anna', 4200),
    (2, 'Ben', 3900),
    (3, 'Cara', 5100);

Пример 1: товар по id через IN

DELIMITER $$

CREATE PROCEDURE get_product_name(IN product_id INT)
BEGIN
    SELECT product_name
    FROM products
    WHERE id = product_id;
END $$

DELIMITER ;

CALL get_product_name(2);

Ожидаемый результат: одна строка с названием Mouse.

Пример 2: годовая зарплата через OUT

DELIMITER $$

CREATE PROCEDURE get_annual_salary(IN emp_id INT, OUT annual_salary INT)
BEGIN
    SELECT monthly_salary * 12
    INTO annual_salary
    FROM employees
    WHERE id = emp_id;
END $$

DELIMITER ;

SET @annual_salary = 0;
CALL get_annual_salary(1, @annual_salary);
SELECT @annual_salary;

Ожидаемый результат: 50400, потому что 4200 * 12 = 50400.

Пример 3: бонус через INOUT

DELIMITER $$

CREATE PROCEDURE increase_bonus(INOUT bonus_amount DECIMAL(10, 2))
BEGIN
    SET bonus_amount = bonus_amount * 1.15;
END $$

DELIMITER ;

SET @bonus = 1000.00;
CALL increase_bonus(@bonus);
SELECT @bonus;

Ожидаемый результат: 1150.00. Здесь @bonus сначала вход, затем контейнер для изменённого значения.