Продолжение поста «Она танцует)»1
Ссылка на музыкальный танцующий Санта-Клаус в комментариях
Если вы работаете с базой данных и начали заглядывать не только в обычные SELECT, рано или поздно встретите два слова: функция и процедура.
На первый взгляд они практически близнецы.
И там, и там можно объявить переменные, поставить условия, сделать запрос к таблице, организовать циклы и вообще спрятать довольно большую часть логики внутри одного объекта.
Тогда возникает вполне логичный вопрос:
а зачем вообще два разных объекта, если они умеют примерно одно и то же?
А в моем канале Аналитика FM выпуски про бизнесовые метрики в разных бизнесах, про особенности SQLзапросов и работы аналитика.
Канал я веду с нуля подписчиков, рассказываю про аналитику и разбираю различные кейсы на реальных примерах.
Подписывайся, если интересно как устроен мир аналитика!
Разница на самом деле довольно простая.
Функция нужна тогда, когда мы хотим что-то получить в результате.
Процедура - когда нам нужно что-то сделать.
Например, представим, что в базе есть таблица клиентов, а нам нужно определить, является ли клиент активным.
Можно сделать функцию:
CREATE OR REPLACE FUNCTION is_active_client( p_client_id NUMBER )
RETURN NUMBER IS v_status VARCHAR2(20);
BEGIN SELECT status
INTO v_status
FROM clients
WHERE client_id = p_client_id;
IF v_status = 'ACTIVE' THEN RETURN 1;
ELSE RETURN 0;
END IF;
END;
Здесь функция получает client_id, что-то делает внутри и обязательно возвращает результат.
Поэтому её можно использовать непосредственно в SQL:
SELECT client_id, is_active_client(client_id) AS is_active FROM clients;
Получается довольно естественная конструкция:
«Вот тебе клиент. Скажи, активный он или нет».
Функция ответила — 1 или 0.
А теперь представим совершенно другую задачу.
Нам нужно массово обновить статус клиентов, записать информацию об операции в журнал и, возможно, выполнить ещё несколько действий.
Для этого больше подходит процедура:
CREATE OR REPLACE PROCEDURE update_client_status(
p_client_id NUMBER,
p_status VARCHAR2 )
IS BEGIN
UPDATE clients
SET status = p_status
WHERE client_id = p_client_id;
INSERT INTO client_log(client_id, action_date)
VALUES (p_client_id, SYSDATE);
END;
Здесь нам не нужно спрашивать у процедуры:
«Какой результат ты мне вернёшь?»
Мы говорим:
«Возьми этого клиента, измени ему статус и запиши информацию об изменении».
То есть процедура выполняет действие.
И вот здесь появляется важное отличие.
У функции есть RETURN.
Например:
RETURN NUMBER
Она может вернуть:
число;
строку;
дату;
другой тип данных;
иногда даже сложный объект.
Поэтому функция хорошо подходит для вычислений и получения какого-то значения.
Например:
SELECT calculate_revenue(client_id) FROM clients;
или:
SELECT order_id, calculate_discount(order_id) AS discount FROM orders;
Процедура может:
INSERT
UPDATE
DELETE
вызывать другие процедуры и функции, работать с переменными, условиями, циклами и выполнять достаточно сложную бизнес-логику.
Вызов процедуры выглядит иначе:
BEGIN
update_client_status(123, 'ACTIVE');
END;
Мы не используем её как обычное значение внутри SELECT.
Мы просто запускаем действие.
И здесь есть интересный нюанс.
Процедура тоже может что-то вернуть через OUT-параметры.
Поэтому говорить:
"процедура ничего не возвращает"
не совсем корректно.
Она может передать вызывающему коду результаты своей работы.
Но концептуально разница остаётся:
функция отвечает на вопрос "что получилось?"
процедура отвечает на вопрос "что нужно сделать?"
Вот здесь начинается самое интересное.
Представьте, что правило расчёта скидки используется в десяти разных местах системы.
Можно десять раз написать/запустить один и тот же SQL запрос.
Но тогда однажды бизнес скажет:
"Теперь скидка считается по новым правилам".
И начинается веселье.
Нужно найти все десять мест и исправить логику.
Вместо этого можно вынести правило в функцию:
calculate_discount(...)
И теперь разные запросы используют одну и ту же логику.
Изменили функцию - изменилось правило расчёта в одном месте.
С процедурами похожая история.
Если в компании есть сложная последовательность действий, её можно спрятать за одной процедурой.
Например:
создать договор → записать клиента → создать связанные записи → записать информацию в журнал → изменить статус
Вместо того чтобы каждый разработчик реализовывал всё это самостоятельно, можно вызвать одну процедуру, которая уже знает, как именно компания должна выполнить эту операцию.
И вот поэтому функции и процедуры в Oracle - это не просто "два разных вида".
Это способ собрать бизнес-логику внутри базы и переиспользовать её.
При этом аналитику не обязательно каждый день создавать процедуры и функции.
Но понимать их очень полезно.
Если вам интересны именно такие нюансы - не только синтаксис, но и то, как всё это устроено в реальной работе аналитика, - я разбираю их в своём Telegram-канале "Аналитика FM". Там как раз про SQL, данные и те самые моменты, на которых чаще всего приходится останавливаться и разбираться.
Когда-то давно читал Лукьяненко, вроде Черновик. Там были люди-функционалы. То есть, буквально: я существую чтобы быть функцией. Сейчас я расскажу о людях-функциях в жизни. Раньше я и сам сопротивлялся, возмущался, плакал, и отрицал сие, как явление в целом. Возможно прочитав этот пост, вы поймете о чем я. Я не знаю как в других странах, но, в России, вам запросто могут нахамить в мишленовском ресторане. Ну нет у нас правильного понятия сферы услуг. Если вы попали в эту сферу - знайте, вы перестали быть человеком и стали функцией. Примеры? Валом. Захожу в магазин, на меня ноль внимания, продавец, на весь магазин, общаясь по телефону, разглагольствует матом, ей вообще плевать, что я пришёл. Это ее магазин, может быть? Ну, чтобы хоть как-то оправдать такое поведение. Вроде нет. Ок, со мной не поздоровались, хотя я пожелал доброго дня. На меня вообще не обратили внимания. Это вот так почему? Это с какого хера функция(продавец), решила подзабить хер на покупателя(приносителя денег)? Кто позволил? Или вот вчера: еду в такси, начинаем добродушно разговаривать(не, я не против, хотя опять же - ты функция. Твое дело меня переместить из точки в точку, это буквально твоя работа) и он начинает вставлять слова между матами. Почему? Кто тебе, функции, позволил так разговаривать с клиентом? Или недавно администратор одной базы отдыха стала жаловаться что отдыхающие имеют претензии: то белье у них влажное(это море, тут влажно!), то мокрицы в углах домика(это море, тут мокрицы!)... Как ей объяснить, что люди ЗАПЛАТИЛИ ЗА СЕРВИС КОТОРЫЙ НЕ ПОЛУЧАЮТ? Вопрос риторический.
Беда нашей сферы обслуживания именно в людях. Да, люди, на работе, выполняя функционал, продолжают считать себя людьми. А это в корне неверно. Стоит покупатель и хамит? Функция не может нахамить в ответ. Это не значит, что вы должны сглотнуть, это значит, что вы не должны хамить в ответ. Я человек, я имею право! Заявление клади на стол и имей право. А пока работаешь - не имеешь, функции вообще все похрен должно быть. Таксист не везет, продавец не продает, официант не обслуживает. Потому что, ишь ты, честь задели, нахамили. Наверное обижаются, когда их в интернете нахуй посылают. Вы уж как-то определитесь, вам сервис нужен? Тогда какого хрена вы не можете предоставить его сами? Сгладить где надо, пропустить мимо ушей, где-то попытаться выправить ситуацию? Я работал в охране ночного клуба, если бы, на каждое обещание расколотить мне лицо, я бы вскидывался, сейчас был бы либо труп, либо чемпион, третьего не дано. Вот только я бы там не работал. Потому что работодателю нахер не нужен агрессивный человек, из-за которого могут быть проблемы. Что, предлагаешь, если нахуй пошлют, просто проглотить? Конечно нет. Зови начальника и пусть он дальше сам вывозит, ты сделал все что мог. Но. Ты резко вспоминаешь что ты, оказывается, человек чести. С чего вдруг?) Ты - функция. Ты не человек. Непонятно? Почему ты хамство воспринимаешь как личное? Хамят не тебе лично, хамят функции! На меня орал покупатель, я ему резонно заметил, что его заказ даже не я обрабатывал, на что он ответил - да мне похуй! Ты - представитель фирмы, ты и отвечай! И он прав. Представляете? Он ведь не на конкретные ФИО орет, он заплатил денег и хочет получить то, что ему, за эти деньги, обещали. А кто перед ним - тот, кто обещал, или любой кто относится к тому, кто обещал - уже не имеет значения. Понятное дело, что, если человек орет на охранника, за то, что ему что-то не продали, тут уже клиника, однако, зачем ему на это указывать? Действуй в рамках инструкции. Поорет и уйдет, а жизнь функции продолжится. Орут не на вас лично, хамят не вам лично, вас вообще за людей не считают и правильно делают, ведь на работе вы не люди, а функция, смиритесь и не принимайте на свой счет. Иначе у нас так и останутся одни кубаноиды(коих мы все не любим за то, что они решили, что они люди, а не функция). Короче, добро пожаловать в сферу услуг, детка.
З. Ы.
Читатель может подумать что ТС весь такой барин. Хер там плавал, ТС тоже функция. Просто я пришёл к этому пониманию, а вы, пока что, нет. То не страшно, придете, рано или поздно. А, ну и это - хер вам, а не панамка, топите так.
Я не согласный, я имею право, я человек! В жизни - да. На работе - хер там плавал. Улыбаемся и машем. Так и появится сервис.