ПрограммированиеDatabase Developer / Архитектор БД

Как правильно создавать и использовать подпрограммы (Procedure/Function) в SQL для реализации повторно используемой бизнес-логики, и какие есть тонкости управления параметрами и возвращаемыми значениями?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Подпрограммы в SQL бывают двух видов:

  • Процедуры (Stored Procedures): выполняют действия (вставка, обновление, удаление), могут возвращать OUT-параметры или наборы строк (через SELECT). Вызываются с помощью CALL/EXEC и не всегда используются в select-прослойке.
  • Функции (User Defined Functions, UDF): возвращают значение (скалярное или табличное), могут использоваться прямо в SELECT, WHERE, ORDER BY и прочих конструкциях.

Важно:

  • Процедуры НЕ могут использоваться в обычном SELECT, только через вызов с EXEC/CALL.
  • Функции могут возвращать только одно значение (скалярные) либо таблицу (табличные функции), и могут использоваться в любом выражении.
  • Всегда документируйте параметры: IN (для входа), OUT (для возврата результата), INOUT (двусторонние).

Пример скалярной функции (PostgreSQL):

CREATE FUNCTION get_tax(amount NUMERIC, rate NUMERIC DEFAULT 0.13) RETURNS NUMERIC AS $$ BEGIN RETURN amount * rate; END; $$ LANGUAGE plpgsql; -- использование: SELECT *, get_tax(price) AS tax FROM product;

Пример хранимой процедуры (SQL Server):

CREATE PROCEDURE add_employee(@name NVARCHAR(100), @salary INT, @emp_id INT OUTPUT) AS BEGIN INSERT INTO employees (name, salary) VALUES (@name, @salary); SET @emp_id = SCOPE_IDENTITY(); END; DECLARE @id INT; EXEC add_employee 'John', 100000, @id OUTPUT;

Вопрос с подвохом.

Можно ли использовать хранимую процедуру напрямую в SELECT?

Часто отвечают "да", но это неверно.

Ответ:

  • Нельзя: стандартные процедуры вызываются только отдельно (EXEC/CALL), а вот функции — можно использовать в SELECT.

Примеры реальных ошибок из-за незнания тонкостей темы.


История

Проект: Система первичного учета, реализация отчетов. Ошибка: Вместо функции написали процедуру для вычисления суммы —SELECT не работал, пришлось переписывать всю логику пользователских отчетов.


История

Проект: ERP-система с внешними параметрами. Ошибка: Для процедуры не задали OUT-ключ, в результате клиент не мог узнать ID добавленной записи, интеграция "сломалась".


История

Проект: Финансовый сервис с рассчетами налога по разным правилам. Ошибка: Использовали скалярную функцию в массовом запросе без теста на производительность — запрос затормозил обработку таблицы из-за построчного вызова (не оптимизированный план).