Входные и выходные параметры процедур и функций
Параметры: входные vs. выходные 🔄
Процедуры и функции — это «чёрные ящики» в SQL. Чтобы они работали эффективно, нужно правильно передавать данные внутрь и получать результаты. Давайте разберёмся, как управлять этим потоком!
Входные параметры (IN) — данные, которые мы передаём в процедуру/функцию.
Выходные параметры (OUT) — результаты, которые возвращаются наружу.
-- Пример процедуры с входным и выходным параметром
CREATE OR REPLACE PROCEDURE calculate_tax(
IN salary NUMERIC, -- Входной параметр
OUT tax NUMERIC -- Выходной параметр
) AS $$
BEGIN
tax := salary * 0.13; -- Рассчитываем налог 13%
END;
$$ LANGUAGE plpgsql;
Функции: возврат значения через RETURN 🎯
Функции обязаны возвращать значение. Для этого используется оператор RETURN.
-- Функция, возвращающая сумму двух чисел
CREATE OR REPLACE FUNCTION add_numbers(
a INTEGER,
b INTEGER
) RETURNS INTEGER AS $$
BEGIN
RETURN a + b; -- Явный возврат результата
END;
$$ LANGUAGE plpgsql;
-- Вызов
SELECT add_numbers(5, 3); -- Вернёт 8
🔥 Важно! В функциях выходные параметры (OUT) используются редко — их заменяет RETURN.
Процедуры: когда OUT побеждает 🏆
Процедуры не возвращают значения через RETURN, зато могут иметь несколько выходных параметров!
-- Процедура с двумя выходными параметрами
CREATE OR REPLACE PROCEDURE get_employee_stats(
IN emp_id INTEGER,
OUT name VARCHAR,
OUT projects_count INTEGER
) AS $$
BEGIN
SELECT full_name INTO name FROM employees WHERE id = emp_id;
SELECT COUNT(*) INTO projects_count FROM projects WHERE owner_id = emp_id;
END;
$$ LANGUAGE plpgsql;
-- Вызов
CALL get_employee_stats(1, NULL, NULL); -- Заполнит выходные параметры
💡 Лайфхак: В PostgreSQL можно опустить NULL при вызове — достаточно CALL get_employee_stats(1).
INOUT: гибридный режим ⚡
Параметр может быть и входным, и выходным одновременно!
-- Функция увеличивает зарплату и возвращает новое значение
CREATE OR REPLACE FUNCTION increase_salary(
INOUT current_salary NUMERIC,
IN bonus NUMERIC
) AS $$
BEGIN
current_salary := current_salary + bonus;
END;
$$ LANGUAGE plpgsql;
-- Вызов
SELECT increase_salary(50000, 10000); -- Вернёт 60000
Продвинутые техники 🚀
1. Значения по умолчанию
CREATE FUNCTION greet(name VARCHAR DEFAULT 'Гость')
RETURNS VARCHAR AS $$
BEGIN
RETURN 'Привет, ' || name || '!';
END;
$$ LANGUAGE plpgsql;
SELECT greet(); -- Привет, Гость!
SELECT greet('Иван'); -- Привет, Иван!
2. Именованные параметры
CREATE FUNCTION create_user(
login VARCHAR,
is_admin BOOLEAN DEFAULT FALSE
) RETURNS VOID AS $$
BEGIN
-- Регистрация пользователя
END;
$$ LANGUAGE plpgsql;
-- Читаемый вызов!
SELECT create_user(login => 'danila', is_admin => TRUE);
Ошибки, которые ломают код 💥
❌ Смешивание RETURN и OUT в функциях
-- Так не делайте!
CREATE FUNCTION confusion()
RETURNS INTEGER AS $$
DECLARE
result INTEGER;
BEGIN
RETURN 42; -- Возврат через RETURN
result := 100; -- Но есть OUT-переменная (ошибка в некоторых СУБД)
END;
$$ LANGUAGE plpgsql;
✅ Правильный подход
CREATE FUNCTION clarity()
RETURNS INTEGER AS $$
DECLARE
result INTEGER;
BEGIN
result := 42;
RETURN result; -- Всё прозрачно!
END;
$$ LANGUAGE plpgsql;
Практика: пишем реалистичные примеры 🛠️
Пример 1: Расчёт НДС
CREATE FUNCTION calculate_vat(
amount NUMERIC,
vat_rate NUMERIC DEFAULT 0.20
) RETURNS NUMERIC AS $$
BEGIN
RETURN amount * vat_rate;
END;
$$ LANGUAGE plpgsql;
-- Использование
SELECT amount, calculate_vat(amount) AS vat FROM invoices;
Пример 2: Обновление статуса заказа
CREATE PROCEDURE update_order_status(
IN order_id INTEGER,
IN new_status VARCHAR,
OUT old_status VARCHAR
) AS $$
BEGIN
SELECT status INTO old_status FROM orders WHERE id = order_id;
UPDATE orders SET status = new_status WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;
-- Вызов
CALL update_order_status(123, 'shipped', NULL);
Теперь ты мастер параметров! 🎓
Попробуй создать свою процедуру с тремя параметрами: один IN, один OUT и один INOUT. Экспериментируй с разными типами данных — даты, JSON, массивы!
Как говорит Данила Бежин: «Параметры — это мосты между вашим кодом и внешним миром. Стройте их надёжно!» 🌉
👉 Больше практики — на YouTube-канале Данилы.