Открыть сервис

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 →