Функции на процедурном языке PL/pgSQL
Last updated
Last updated
PostgreSQL позволяет разрабатывать пользовательские функции не только на SQL и C, но и на процедурных языках (PL, Procedural Language). В настоящее время стандартный дистрибутив PostgreSQL включает четыре процедурных языка: PL/pgSQL, PL/Tcl, PL/Perl и PL/Python. В своей практике мы используем язык PL/pgSQL.
Ключевые преимущества PL/pgSQL:
добавляет управляющие структуры к языку SQL;
может выполнять сложные вычисления;
наследует все пользовательские типы, функции и операторы;
прост в использовании.
Подробно о процедурном языке PL/pgSQL можете почитать на официальном сайте в разделе Глава 41. PL/pgSQL — процедурный язык SQL. В этой статье кратко рассмотрим особенности функций на процедурном языке.
В плане объявления аргументов и выходных значений синтаксис функций на PL/pgSQL соответствуют синтаксису SQL-функций, которые рассматриваются в статье:
Функции на PL/pgSQL могут принимать в качестве аргументов все поддерживаемые сервером скалярные типы данных или массивы и возвращать в качестве результата любой из этих типов. Они могут принимать и возвращать именованные составные типы (строковый тип). Есть возможность объявить функцию на PL/pgSQL, возвращающую record
- строковый тип, чьи столбцы будут определены в спецификации вызывающего запроса.
Функции на PL/pgSQL могут возвращать "множества" (или таблицы) любого типа, которые могут быть возвращены в виде одного объекта. Такие функции генерируют вывод, выполняя команду RETURN NEXT
для каждого элемента результирующего набора или RETURN QUERY
для вывода результата запроса.
При отсутствии полезного возвращаемого значения функция на PL/pgSQL может возвращать void
.
Функции на PL/pgSQL можно объявить с выходными параметрами вместо явного задания типа возвращаемого значения. Это не добавляет никаких фундаментальных возможностей языку, но часто бывает удобно, особенно для возвращения нескольких значений.
Основное отличие функций на языке PL/pgSQL заключается в блочной структуре текста тела функции:
В блоке DECLARE
объявляются переменные, которым можно задавать константные значения, либо присваивать результаты выполнения SQL-команд и вызова других функций.
Правила выполнения команд SQL, логика присваивания значений рассматриваются в разделе 41.5. Основные операторы на официальном сайте.
После ключевого слова BEGIN
задаются управляющие структуры (41.6. Управляющие структуры):
Условные операторы IF
и CASE
- позволяют выполнять команды в зависимости от определённых условий;
Простые циклы LOOP
, WHILE
и FOR
- позволяют повторить серию команд;
Цикл по результатам запроса FOR
;
Цикл по элементам массива FOREACH
;
Секция EXCEPTION
- позволяет перехватывать и обрабатывать ошибки.
В качестве примера рассмотрим функцию удаления записи:
Первым делом проверяем, существует ли удаляемая запись. Если записи в таблице нет, то завершаем выполнении функции с помощью оператора RETURN
. Затем проверяем, есть ли в других таблицах ссылки на удаляемую запись, для этого вызываем функцию template.is_used(). Если идентификатор используется, то отправляем запись в архив, иначе удаляем.
Процедурный язык позволяет создавать анонимные функции, которые можно использовать напрямую в тэге <SqlQuery>
в серверном xml-файле, что открывает возможности применять переменные и управляющие структуры.
Ключевое слово DO
описывает блок кода, который выполняет разовую анонимную функцию на процедурном языке:
Блок кода воспринимается, как тело функции, которая не имеет параметров и возвращает void
. Этот код разбирается и выполняется один раз.
Простой пример анонимной функции:
В примере проверяем существование записи города в таблице template.city. Если такой записи нет, то создаем, иначе обновляем существующую.