Структура PL/pgSQL
Функции, написанные на PL/pgSQL, определяются на сервере путем выполнения команд CREATE FUNCTION. Такая команда обычно выглядит примерно так:
CREATE FUNCTION somefunc(integer, text) RETURNS integer
AS 'текст тела функции'
LANGUAGE plpgsql;
В контексте команды CREATE FUNCTION тело функции представляет собой просто
строковый литерал. Часто для написания тела функции полезно использовать
долларовые кавычки (см. подраздел Строковые константы, заключенные в знаки доллара)
вместо обычного синтаксиса с апострофами. Без долларовых кавычек любые апострофы
или обратные слэши в теле функции следует экранировать путем их удвоения. Почти
во всех примерах в этой главе для тел функций используются литералы в долларовых
кавычках.
PL/pgSQL — это блочно-структурированный язык. Полный текст тела функции должен быть блоком. Блок определяется как:
[ <<метка>> ]
[ DECLARE
объявления ]
BEGIN
операторы
END [ метка ];
Каждое объявление и каждый оператор в блоке заканчиваются точкой с запятой. Блок,
находящийся внутри другого блока, должен иметь точку с запятой после END, как
показано выше; однако последний END, завершающий тело функции, точки с запятой
не требует.
Совет
Распространенная ошибка — писать точку с запятой сразу послеBEGIN. Это неверно и приведет к синтаксической ошибке.
метка нужна только в том случае, если вы хотите идентифицировать блок
для использования в операторе EXIT или указать имена переменных, объявленных в
этом блоке. Если метка задается после END, она должна совпадать с меткой в
начале блока.
Все ключевые слова нечувствительны к регистру. Идентификаторы, если они не заключены в кавычки, как в обычных командах SQL, неявно переводятся в нижний регистр.
Комментарии в коде PL/pgSQL работают так же, как и в обычном SQL. Комментарий начинается после двойного дефиса (--) и продолжается до конца строки. Блочный комментарий начинается с символов /* и продолжается до зеркальных символов */. Блочные комментарии могут быть вложенными.
Любой оператор в разделе операторов блока может быть субблоком. Субблоки можно использовать для логической группировки или для локализации переменных в небольшой группе операторов. Переменные, объявленные в субблоке, скрывают на время его выполнения любые переменные внешних блоков с теми же именами; но ко внешним переменным все равно можно обратиться, если дополнить их имена меткой их блока. Например:
CREATE FUNCTION somefunc() RETURNS integer AS $$
<< outerblock >>
DECLARE
quantity integer := 30;
BEGIN
RAISE NOTICE 'Quantity here is %', quantity; -- Выводится 30
quantity := 50;
--
-- Создать субблок
--
DECLARE
quantity integer := 80;
BEGIN
RAISE NOTICE 'Quantity here is %', quantity; -- Выводится 80
RAISE NOTICE 'Outer quantity here is %', outerblock.quantity; -- Выводится 50
END;
RAISE NOTICE 'Quantity here is %', quantity; -- Выводится 50
RETURN quantity;
END;
$$ LANGUAGE plpgsql;
Примечание
На самом деле существует скрытый «внешний блок», окружающий тело любой функции PL/pgSQL. Этот блок предоставляет объявления параметров функции (если таковые имеются), а также некоторые специальные переменные, например FOUND (см. подраздел Получение статуса результата). Внешний блок помечается именем функции, подразумевая, что параметры и специальные переменные можно дополнить именем функции.
Важно не путать использование BEGIN/END для группировки операторов в PL/pgSQL
с одноименными командами SQL для управления транзакциями. В PL/pgSQL BEGIN/END
предназначены только для группировки; они не начинают и не заканчивают транзакцию.
Информацию об управлении транзакциями в PL/pgSQL см. в разделе Управление транзакциями.
Кроме того, блок, содержащий предложение EXCEPTION, по сути образует
субтранзакцию, которую можно откатить, не затрагивая внешнюю транзакцию. Подробнее
это описано в подразделе Перехват ошибок.