Что такое хранимая процедура в SQL?

Ответ

Хранимая процедура — это предварительно скомпилированный и сохраненный на сервере базы данных набор SQL-инструкций, который выполняется как единая логическая единица.

Преимущества:

  1. Производительность: Выполняется на стороне СУБД, уменьшая сетевой трафик и время компиляции.
  2. Безопасность: Можно предоставлять права на выполнение процедуры, не открывая прямой доступ к таблицам.
  3. Повторное использование и централизация логики: Бизнес-логика инкапсулируется в БД и может вызываться из разных приложений.
  4. Упрощение поддержки: Изменения вносятся в одном месте (на сервере БД).

Недостатки:

  • Перенос логики в БД усложняет отладку и тестирование.
  • Привязывает приложение к конкретной СУБД (проблема переносимости).
  • Может создавать нагрузку на сервер БД.

Пример создания и вызова (MySQL/Java):

-- Создание процедуры в БД
DELIMITER //
CREATE PROCEDURE GetEmployeeName(IN empId INT, OUT empName VARCHAR(100))
BEGIN
    SELECT name INTO empName FROM employees WHERE id = empId;
END //
DELIMITER ;
// Вызов из Java с использованием JDBC
String call = "{call GetEmployeeName(?, ?)}";
try (CallableStatement stmt = connection.prepareCall(call)) {
    stmt.setInt(1, 123); // Установка входного параметра (IN)
    stmt.registerOutParameter(2, Types.VARCHAR); // Регистрация выходного параметра (OUT)
    stmt.execute();
    String result = stmt.getString(2); // Получение результата
    System.out.println("Employee name: " + result);
}

Ответ 18+ 🔞

А, ну вот, опять про эти ваши хранимые процедуры, блядь! Сидит человек, думает: "О, сейчас я логику в базу засуну, и будет мне счастье!" А потом, сука, волосы на жопе рвёт, когда её отлаживать надо. Давайте по полочкам, но с пристрастием, ёпта.

Короче, хранимка — это типа такой заготовленный скрипт, который живёт прямо внутри базы данных, как её родной, ёбаный, сын. Не надо каждый раз из приложения слать кучу запросов — назвал одну команду, и она там на сервере сама всё сделает, как надо.

Чем это, блядь, хорошо, спросите вы?

  1. Быстрота, мать её. Всё крутится прямо на сервере БД. Не надо туда-сюда по сети пакеты гонять и каждый раз запрос парсить. Один раз скомпилировали — и поехали.
  2. Безопасность, ёпта. Можно дать юзеру права просто процедуру вызывать, а к самим таблицам доступ не открывать. Чтоб он там чего лишнего не нахулиганил, пидарас шерстяной.
  3. Логика в одном месте. Представь, у тебя десять сервисов одно и то же делают. Вместо того чтобы в каждом коде эту хуйню дублировать, пишешь одну процедуру — и все её дергают. Красота! Поменял логику в одном месте — и везде обновилось. В рот меня чих-пых, удобно же!
  4. Поддержка проще. Искать баг не по всему коду, а в одном конкретном куске на сервере БД. Хотя, конечно, если процедура на сто строк — это уже пиздец, а не поддержка.

А теперь, сука, ложка дёгтя, размером с лопату:

  • Отладка — это ад. Ты попробуй пошагово выполнить эту хрень, когда она там, в недрах СУБД, сидит. Чувствуешь подозрение, блядь? Правильно чувствуешь.
  • Привязка к вендору. Написал под MySQL — и сиди на нём, как приклеенный. Захотел на PostgreSQL переехать? Ну, удачи тебе, чувак, переписывай всю эту муть. Переносимость — ноль ебать.
  • Нагрузка на базу. Вся логика теперь грузит сервер БД, а не сервер приложения. Сделаешь криво — и твоя база ляжет, как опоенная муха, под медным тазом.

Ну и, собственно, как этим пользоваться, чтобы потом не было мучительно больно. Смотри, вот тебе пример, как это в MySQL забабахать и из Java вызвать:

-- Вот так эту процедуру на сервере создаёшь
DELIMITER //
CREATE PROCEDURE GetEmployeeName(IN empId INT, OUT empName VARCHAR(100))
BEGIN
    SELECT name INTO empName FROM employees WHERE id = empId;
END //
DELIMITER ;

А теперь, внимание, вызываем эту красоту из Java. Главное — не обосраться с параметрами.

// Готовим вызов, как будто заклинание какое-то
String call = "{call GetEmployeeName(?, ?)}";
try (CallableStatement stmt = connection.prepareCall(call)) {
    stmt.setInt(1, 123); // Суём на вход ID (IN-параметр)
    stmt.registerOutParameter(2, Types.VARCHAR); // Говорим, что второй параметр — выходной (OUT), будет имя
    stmt.execute(); // И поехали!
    String result = stmt.getString(2); // Вытаскиваем результат оттуда
    System.out.println("Employee name: " + result); // И вуаля, блядь
}

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