Структура языка
Выражения
Выражения представляют собой условную запись последовательности операций, результат которой принадлежит одному из базовых типов данных PostgreSQL. В листинге 11.8 приведена простая функция PL/pgSQL, возвращающая результат простого выражения, а в листинге 11.9 продемонстрирован результат вызова этой функции в psql.
Листинг 11.8. Использование выражений.
CREATE FUNCTION a_function () RETURNS int4 AS ' DECLARE an_integer 1nt4; BEGIN an_integer: = 10 * 10: return an_integer; END: ' LANGUAGE 'plpgsql';
Листинг 11.9. Результат вызова функции a_function().
booktown=# SELECT a_function() AS output: output 100 (1 row)
Если не считать динамических запросов (запросов SQL, выполняемых с ключевым словом EXECUTE), все выражения PL/pgSQL в функциях обрабатываются только один раз на протяжении работы серверного процесса PostgreSQL. Поскольку выражения обрабатываются однократно, константные значения (такие, как временные метки now и current) в выражениях PL/pgSQL тоже обрабатываются только один раз, что приводит к нарушению работы программ, требующих интерпретации констант на стадии выполнения. В листинге 11.10 показано, как в PL/pgSQL организуется обработка константных временных меток во время работы функции.
Функция add_shipment в листинге 11.11 использует многие приемы и особенности языка, описанные ниже в этой главе. Функция получает код покупателя и код ISBN книги и вычисляет код следующей поставки, увеличивая на 1 текущий максимальный код поставки, после чего вставляет запись в таблицу shipments с временной меткой now.
Если бы метка now использовалась непосредственно в команде INSERT INTO, то строка now была бы преобразована в текущее время при создании функции и полученное значение использовалось бы во всех последующих вызовах функции.
Листинг 11.10. Правильное использование временных меток.
CREATE FUNCTION add_shipment (integer, text) RETURNS timestamp AS ' DECLARE --Объявление псевдонимов для аргументов функции, customerjd ALIAS FOR $1: isbn ALIAS FOR $2; --Объявление переменных для хранения кода поставки и текущего времени. shipment_1d integer; rightjiow timestamp; BEGIN --Присвоить переменной текущего времени строку ''now' right_now: = ''now'': --Упорядочить существующие поставки по убыванию кодов --и присвоить первый код переменной shipment_id. SELECT INTO shlpmentjd id FROM shipments ORDER BY id DESC: --Увеличить переменную shipment_id на 1. shipment_id: = shipment_id + 1: --Вставить запись в таблицу shipments. --Переменная rightjiow преобразуется к временной пометке на стадии --выполнения программы, вследствие чего константное значение now --интерпретируется заново при каждом вызове функции. INSERT INTO shipments VALUES (shipmentjd .customeMd .isbn .rightjnow): --Вернуть временную пометку, используя константу now. RETURN rightjiow: END: ' LANGUAGE 'plpgsql';