40.2. Структура PL/pgSQL#
40.2. Структура PL/pgSQL #
Функции, написанные на языке PL/pgSQL, определяются на сервере путем выполнения команд CREATE FUNCTION. Обычно такая команда выглядит, скажем, так:
CREATE FUNCTION somefunc(integer, text) RETURNS integer
AS 'function body text'
LANGUAGE plpgsql;
Тело функции представляет собой просто строковый литерал, что касается CREATE FUNCTION. Часто полезно использовать кавычки доллара (см. Раздел 4.1.2.4) для написания тела функции, вместо обычного синтаксиса с апострофами. Без использования кавычек доллара, любые апострофы или обратные косые черты в теле функции должны быть экранированы удвоением. Почти все примеры в этой главе используют литералы с кавычками доллара для своих тел функций.
PL/pgSQL - это язык с блочной структурой. Полный текст тела функции должен быть блоком. Блок определяется следующим образом:
[ <<label>> ] [ DECLAREdeclarations] BEGINstatementsEND [label];
Каждое объявление и каждый оператор внутри блока завершаются точкой с запятой. Блок, который находится внутри другого блока, должен иметь точку с запятой после END, как показано выше; однако последний END, который завершает тело функции, не требует точки с запятой.
Подсказка
Частой ошибкой является написание точки с запятой непосредственно после
BEGIN. Это неправильно и приведет к синтаксической ошибке.
Метка label необходима только в том случае, если нужно идентифицировать блок для использования в операторе EXIT или для квалификации имен переменных, объявленных в блоке. Если метка указана после END, она должна совпадать с меткой в начале блока.
Все ключевые слова нечувствительны к регистру. Идентификаторы неявно преобразуются в нижний регистр, если они не заключены в двойные кавычки, так же, как в обычных SQL-командах.
Комментарии работают так же в коде PL/pgSQL, как и в обычном SQL. Два дефиса (--) начинает комментарий, который продолжается до конца строки. /* начинает блочный комментарий, который продолжается до соответствующего ввода */. Блочные комментарии могут быть вложенными.
Любое оператор в разделе операторов блока может быть подблоком. Подблоки могут использоваться для логической группирования или для локализации переменных в небольшой группе операторов. Переменные, объявленные в подблоке, замещают любые переменные с аналогичными именами во внешних блоках на время выполнения подблока; однако вы все равно можете обращаться к внешним переменным, если указываете их имена с меткой их блока. Например:
CREATE FUNCTION somefunc() RETURNS integer AS $$
<< outerblock >>
DECLARE
quantity integer := 30;
BEGIN
RAISE NOTICE 'Quantity here is %', quantity; -- Prints 30
quantity := 50;
--
-- Create a subblock
--
DECLARE
quantity integer := 80;
BEGIN
RAISE NOTICE 'Quantity here is %', quantity; -- Prints 80
RAISE NOTICE 'Outer quantity here is %', outerblock.quantity; -- Prints 50
END;
RAISE NOTICE 'Quantity here is %', quantity; -- Prints 50
RETURN quantity;
END;
$$ LANGUAGE plpgsql;
Примечание
Собственно, вокруг тела любой функции PL/pgSQL на самом деле есть скрытый “внешний блок”. Этот блок содержит объявления параметров функции (если они есть), а также некоторые специальные переменные, такие как FOUND (см. Раздел 40.5.5). Внешний блок помечен именем функции, что означает, что параметры и специальные переменные могут быть полными именами функции.
Важно не путать использование команды BEGIN/END для группирования операторов в PL/pgSQL с аналогичными командами SQL для управления транзакциями. BEGIN/END в PL/pgSQL используются только для группирования, они не начинают и не завершают транзакцию. См. раздел Раздел 40.8 для получения информации о управлении транзакциями в PL/pgSQL. Кроме того, блок, содержащий предложение EXCEPTION, фактически формирует подтранзакцию, которая может быть отменена без влияния на внешнюю транзакцию. Дополнительную информацию об этом см. в разделе Раздел 40.6.8.