PL/pgSQL
PL/pgSQL (Procedural Language/PostgreSQL Structured Query Language) — это процедурное расширение языка SQL, встроенное в систему управления базами данных PostgreSQL. Оно предназначено для создания функций, процедур и триггеров, выполняемых непосредственно на сервере баз данных. PL/pgSQL позволяет использовать переменные, условные операторы, циклы, обработку исключений и другие конструкции, характерные для императивных языков программирования, при этом сохраняя тесную интеграцию с SQL-запросами.
История
PL/pgSQL был разработан как замена языку PL/SQL, используемому в СУБД Oracle, но с адаптацией под архитектуру и возможности PostgreSQL. Первая версия языка появилась в PostgreSQL 6.5 (1999 год). Основным разработчиком выступил Ян Видерхольд (Jan Wieck). Изначально PL/pgSQL был реализован как внешний модуль, но начиная с PostgreSQL 7.0 (2000 год) он стал неотъемлемой частью дистрибутива СУБД. Основной целью создания языка было предоставление разработчикам возможности писать серверный код без необходимости использования внешних языков (таких как C или Perl), что упрощало разработку и повышало безопасность за счёт выполнения кода в контексте сервера.
Основные возможности и синтаксис
PL/pgSQL является блочно-структурированным языком. Каждая функция или процедура представляет собой блок кода, заключённый в конструкцию BEGIN ... END. Блоки могут быть вложенными, и каждый блок может иметь собственную секцию объявления переменных (DECLARE).
Переменные и типы данных
Переменные объявляются в секции DECLARE и могут иметь любой тип данных, поддерживаемый PostgreSQL (включая пользовательские типы, массивы, JSON и т.д.). Также поддерживаются составные типы, создаваемые на основе таблиц или записей.
``sql DECLARE user_id INTEGER; user_name TEXT; total_sales NUMERIC(10,2); ``
Управляющие конструкции
PL/pgSQL поддерживает стандартные управляющие конструкции:
- Условные операторы:
IF ... THEN ... ELSE ... END IF;CASE ... WHEN ... THEN ... END CASE. - Циклы:
LOOP,WHILE,FOR(в том числе по диапазону чисел и по результатам запроса). - Обработка исключений: блок
EXCEPTIONвнутриBEGIN ... ENDпозволяет перехватывать и обрабатывать ошибки (например, нарушение уникальности, деление на ноль).
Взаимодействие с SQL
Ключевая особенность PL/pgSQL — возможность выполнять SQL-запросы непосредственно внутри кода. Для этого используются:
SELECT ... INTO— для выборки данных в переменную.INSERT,UPDATE,DELETE— для модификации данных.EXECUTE— для выполнения динамических SQL-запросов, которые формируются на лету (например, с подстановкой имён таблиц).
Возвращаемые значения
Функции на PL/pgSQL могут возвращать:
- Скалярные значения (одно число, строку, дату и т.д.).
- Составные типы (записи, соответствующие структуре таблицы).
- Таблицы (с помощью
RETURNS TABLE), что позволяет использовать функцию как источник данных вFROM. - Процедуры (начиная с PostgreSQL 11) — не возвращают значения, но могут управлять транзакциями.
Применение
PL/pgSQL широко используется для реализации бизнес-логики на стороне сервера баз данных. Основные сценарии применения:
Хранимые функции и процедуры
Разработчики создают функции, которые инкапсулируют сложные запросы, проверки целостности данных или вычислительные алгоритмы. Это позволяет:
- Сократить сетевой трафик (вместо нескольких запросов отправляется один вызов функции).
- Обеспечить единую точку выполнения логики (централизация правил).
- Повысить безопасность (пользователи получают доступ к данным только через функции, без прямого доступа к таблицам).
Триггеры
PL/pgSQL является основным языком для написания триггеров в PostgreSQL. Триггеры автоматически выполняются при вставке, обновлении или удалении строк в таблице. Они могут использоваться для:
- Аудит-логирования изменений.
- Каскадного обновления связанных данных.
- Проверки сложных бизнес-правил, которые невозможно реализовать через ограничения (
CHECK,UNIQUE).
Обработка ошибок и транзакций
С помощью блоков EXCEPTION можно реализовать устойчивые к ошибкам операции, например, попытку вставки данных с откатом при нарушении уникальности и последующей обработкой альтернативного сценария.
Преимущества и недостатки
Преимущества
- Тесная интеграция с SQL: возможность смешивать императивный код с SQL-запросами без переключения контекста.
- Производительность: выполнение на сервере исключает накладные расходы на передачу данных между клиентом и сервером.
- Безопасность: код выполняется в защищённой среде СУБД, что снижает риски SQL-инъекций при использовании параметризованных запросов.
- Переносимость в рамках экосистемы PostgreSQL: код на PL/pgSQL работает на любой платформе, где развёрнута СУБД.
Недостатки
- Ограниченная область применения: язык предназначен только для работы с данными в PostgreSQL и не подходит для разработки пользовательских интерфейсов, веб-сервисов или сложных вычислительных задач.
- Сложность отладки: инструменты отладки PL/pgSQL менее развиты по сравнению с языками общего назначения (например, Python или Java).
- Производительность при сложных вычислениях: для интенсивных математических или строковых операций PL/pgSQL может уступать языкам, компилируемым в машинный код (C, C++).
Сравнение с другими процедурными языками PostgreSQL
PostgreSQL поддерживает несколько процедурных языков: PL/pgSQL, PL/Python, PL/Perl, PL/Tcl, PL/Java и другие. PL/pgSQL является наиболее распространённым благодаря тому, что:
- Он встроен в дистрибутив по умолчанию (не требует установки дополнительных модулей).
- Он оптимизирован для работы с SQL и не требует настройки внешних интерпретаторов.
- Он обладает наименьшими накладными расходами на запуск (не требует загрузки интерпретатора стороннего языка).
Однако для задач, требующих сложной обработки данных (например, работа с регулярными выражениями, HTTP-запросами, шифрованием), разработчики могут выбирать PL/Python или PL/Perl, которые предоставляют более широкие возможности стандартных библиотек.
Пример простой функции
Ниже приведён пример функции на PL/pgSQL, которая вычисляет скидку на товар в зависимости от суммы покупки:
``sql CREATE OR REPLACE FUNCTION calculate_discount(amount NUMERIC) RETURNS NUMERIC AS $$ DECLARE discount NUMERIC := 0; BEGIN IF amount >= 1000 THEN discount := amount 0.1; -- 10% скидка ELSIF amount >= 500 THEN discount := amount 0.05; -- 5% скидка ELSE discount := 0; END IF; RETURN discount; END; $$ LANGUAGE plpgsql; ``
Эта функция принимает числовой параметр amount и возвращает величину скидки. Она может быть вызвана как в SQL-запросе:
``sql SELECT calculate_discount(1200); -- вернёт 120 ``
Интересные факты
- PL/pgSQL не является полноценным языком программирования общего назначения — в нём отсутствуют, например, массивы как самостоятельный тип данных (хотя поддерживаются массивы PostgreSQL) и работа с файловой системой.
- Название «PL/pgSQL» иногда сокращают до «plpgsql» (в именах файлов, путях установки).
- Несмотря на схожесть с PL/SQL Oracle, PL/pgSQL не является его клоном: различаются синтаксис обработки исключений, работа с курсорами, поддержка динамического SQL.
- В PostgreSQL 11 была добавлена поддержка хранимых процедур (с возможностью управления транзакциями), что ранее было доступно только через функции.
Источники
- PostgreSQL Global Development Group. «PostgreSQL Documentation: Chapter 42. PL/pgSQL — SQL Procedural Language». Официальная документация PostgreSQL.
- Wieck, J. (1999). «PL/pgSQL: A Procedural Language for PostgreSQL». Proceedings of the PostgreSQL Developers Conference.
- Riggs, S., & Krosing, H. (2015). «PostgreSQL 9 Administration Cookbook». Packt Publishing.
- PostgreSQL Community. «PL/pgSQL Guide». PostgreSQL Wiki.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →