Структура 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, по сути образует субтранзакцию, которую можно откатить, не затрагивая внешнюю транзакцию. Подробнее это описано в подразделе Перехват ошибок.