Условные команды
Условная команда указывает на то, что некоторое действие (или последовательность действий) выполняется в зависимости от результатов проверки заданного логического условия. Определение выглядит запутанно, но на самом деле условные команды весьма просты. В неформальной формулировке условная команда означает следующее: «если условие истинно, выполнить такое-то действие».
Команда IF/THEN
В соответствии с данным определением команда IF/THEN задает команду (или блок команд), выполняемых в случае истинности некоторого условия. Синтаксис команды IF/THEN показан в листинге 6.27.
Листинг 6.27. Синтаксис команды IF/THEN
CREATE FUNCTION функция (аргументы) RETURNS тип AS '
DECLARE
объявления
BEGIN
IF условие THEN
команда;
[...]
END IF;
END;
' LANGUAGE ‘plpgsql’ VOLATILE
В листинге 6.28 приведена функция, которая проверяет количество экземпляров книги на складе по коду и номеру издания. Код книги используется во внутрениих операциях базы данных и присутствует в нескольких таблицах.
Следовательно, функция stock_amount() предназначена для вызова из других функций, а не прямого вызова из клиентской программы, поскольку большинству пользователей коды книг неизвестны.
Сначала мы читаем код ISBN командой SELECT INTO. Если команда SELECT INTO не смогла найти код ISBN по заданному коду книги и номеру издания, функция stock_amount() возвращает -1.
Функция, вызвавшая stock_amount(), интерпретирует это значение как признак ошибки. Если код ISBN найден, то другая команда SELECT INTO получает количество экземпляров книги на складе и возвращает полученную величину. На этом работа функции завершается.
Листинг 6.28. Использование команды IF/THEN
CREATE OR REPLACE FUNCTION books.stock_amount(integer, integer)
RETURNS integer AS
$BODY$
DECLARE
-- Объявление псевдонимов для аргументов функции.
b_id ALIAS FOR $1;
b_edition ALIAS FOR $2;
-- Объявление переменной для кода ISBN.
b_isbn text;
-- Объявление переменной для количества экземпляров.
stock_amount integer;
BEGIN
-- Команда SELECT INTO находит в таблице editions запись,
-- у которой код книги и номер издания совпадают с аргументами
-- функции. Код ISBN из найденной записи присваивается переменной.
SELECT INTO b_isbn isbn FROM books.editions WHERE
book_id = b_id AND edition = b_edition;
-- Проверить, не был ли полученный код ISBN равен NULL.
-- Значение NULL говорит о том, что в базе данных
-- не существует записи книги с кодом и номером издания,
-- переданными в аргументах функции. Если запись не существует,
-- функция возвращает -1 и завершает работу.
IF b_isbn IS NULL THEN
RETURN -1;
END IF;
-- Получить из таблицы stock количество экземпляров книги
-- на складе и присвоить его переменной stock_amount.
SELECT INTO stock_amount stock FROM books.stock WHERE isbn = b_isbn;
-- Вернуть количество экземпляров на складе.
RETURN stock_amount;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
В листинге 6.29 показан результат вызова функции stock_amount() для кода книги 7808 и издания 1.
Листинг 6.29. Результаты вызова функции stock_amount()
SELECT books.stock_amount(7808,1);
Ответ: 22.
Команда IF/THEN/ELSE
В команде IF/THEN/ELSE задаются два блока команд. Первый блок выполняется в том случае, если условие истинно, а второй - если оно ложно. Синтаксис команды IF/THEN/ELSE приведен в листинге 6.30.
Листинг 6.30. Синтаксис команды IF/THEN/ELSE
CREATE FUNCTION функция (аргументы) RETURNS тип AS '
DECLARE
объявления
BEGIN
IF условие THEN
команда;
[...]
ELSE
команда;
[...]
END IF;
END;
' LANGUAGE ‘plpgsql’ VOLATILE
Функция в листинге 6.31 делает практически то же, что и функция в листинге 6.28: она также определяет код ISBN по коду книги и номеру издания, сохраняет его в переменной и получает количество экземпляров книги на складе.
Затем команда IF/THEN/ELSE проверяет, является ли количество книг на складе положительной величиной. Если число положительно, функция возвращает TRUE - признак наличия книг на складе. В противном случае функция возвращает FALSE. Стоит напомнить, что функция in_stock() предназначена для вызова из других функций, а возвращаемое значение должно интерпретироваться той функцией, из которой она была вызвана.
Листинг 6.31. Команда IF/THEN/ELSE
CREATE OR REPLACE FUNCTION books.in_stock(integer, integer)
RETURNS boolean AS
$BODY$
DECLARE
-- Объявление псевдонимов для аргументов функции.
b_id ALIAS FOR $1;
b_edition ALIAS FOR $2;
-- Объявление текстовой переменной для найденного кода ISBN.
b_isbn text;
-- Объявление целочисленной переменной для количества экземпляров.
stock_amount integer;
BEGIN
-- Команда SELECT INTO находит в таблице editions запись.
-- у которой код книги и номер издания совпадают с аргументами
-- функции. Код ISBN из найденной записи присваивается переменной.
SELECT INTO b_isbn isbn FROM books.editions WHERE
book_id = b_id AND edition = b_edition;
-- Проверить, не был ли полученный код ISBN равен NULL.
-- Значение NULL говорит о тон. что в базе данных
-- не существует записи книги с кодом и номером издания.
-- переданными в аргументах функции. Если запись не существует.
-- функция возвращает FALSE и завершает работу.
IF b_isbn IS NULL THEN
RETURN FALSE;
END IF;
-- Получить из таблицы stock количество экземпляров книги
-- на складе и присвоить его переменной stock_amount.
SELECT INTO stock_amount stock FROM books.stock
WHERE isbn = b_isbn;
-- Проверить, является ли количество книг на складе
-- положительной величиной. Если количество положительно,
-- функция возвращает TRUE, а если отрицательно
-- или равно нулю - FALSE.
IF stock_amount <= 0 THEN
RETURN FALSE;
ELSE
RETURN TRUE;
END IF;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
В листинге 6.32 показан результат вызова in_stock() для кода книги 4513 и издания 2.
Листинг 6.32. Результат вызова функции in_stock()
SELECT books.in_stock(4513,2);
Ответ: t.
Функция вернула значение TRUE - признак наличия книги на складе.
Команда IF/THEN/ELSE/IF
Команда IF/THEN/ELSE/IF предназначена для последовательной проверки нескольких условий. Сначала проверяется первое условие; если оно окажется равным FALSE, проверяется следующее условие и т. д. Последняя секция ELSE содержит команды, выполняемые в том случае, если пи одно из проверенных условий не было истинным. Синтаксис команды IF/THEN/ELSE/IF:
CREATE FUNCTION функция (аргументы) RETURNS тип AS '
DECLARE
объявление BEGIN
IF условие THEN
команда;
[...]
ELSE IF условие
команда;
[...]
END IF;
END;
' LANGUAGE 'plpgsql' :
В листинге 6.33 приведен практический пример применения функции с командой IF/ THEN/ELSE/IF. Функция books_by_subject() сначала использует переданный аргумент (тему книги) для выборки кода темы. Затем первая команда IF проверяет, не содержит ли переданный аргумент строку all.
Если при вызове был передан аргумент all, команда IF/THEN вызывает функцию extract_all_titles() и присваивает полученный список книг и тем (возвращаемый в виде текстовой переменной) переменной found_text.
Если аргумент отличен от all, следующая команда ELSE IF проверяет, является ли код темы нулем или положительным числом. Если значение sub_id больше либо равно нулю, выполняются команды, содержащиеся в теле конструкции ELSE IF - сначала вызывается функция extract_title(), которая возвращает список всех существующих книг по заданной теме, после чего тема возвращается вместе с полученным списком.
Затем другая команда ELSE IF сравнивает код темы с псевдозначением NULL. Если значение sub_id равно NULL, значит, переданная при вызове функции тема не встречается в базе данных booktown, а выполненная в самом начале команда SELECT INTO завершилась неудачей. В этом случае функция возвращает строку «subject not found».
ПРИМЕЧАНИЕ Функции extract_all_titles() и extract_title(), используемые в листинге 11.40, будут рассмотрены ниже, когда речь пойдет о циклах.
Листинг 6.33. Команда IF/THEN/ELSE/IF
CREATE OR REPLACE FUNCTION books.books_by_subject(text)
RETURNS text AS
$BODY$
DECLARE
-- Объявление псевдонима для аргумента, содержащего либо
-- строку all, либо тему.
sub_title ALIAS FOR $1;
-- Объявление целочисленной переменной для хранения кода темы
-- и текстовой переменной для хранения списка найденных книг.
-- Текстовая переменная инициализируется пустой строкой.
sub_id integer;
found_text text;
BEGIN
-- Получить код темы, описание которой передано в аргументе.
SELECT INTO sub_id id FROM books.subjects WHERE subject = sub_title;
-- Проверить, запросил ли пользователь информацию обо всех темах
-- (строка all). В этом случае вызвать функцию extract_all_titles()
-- и вернуть полученную текстовую переменную.
IF sub_title = 'all'
THEN
found_text := books.extract_all_titles();
RETURN found_text;
-- Если в аргументе НЕ БЫЛА передана строка 'all', проверить,
-- входит ли код темы в интервал допустимых значений.
-- Если это так, вызвать функцию extract_title() с кодом темы
-- и присвоить результат переменной found_text.
ELSE IF sub_id >= 0
THEN
found_text := books.extract_title(sub_id);
RETURN '\n' || sub_title || ':\n' || found_text;
-- Если код темы равен NULL, вернуть сообщение о том, что
-- заданная тема не найдена.
ELSE IF sub_id IS NULL
THEN
RETURN 'Subject not found.';
END IF;
END IF;
END IF;
RETURN 'An error occurred.';
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
В листинге 6.34 сначала приведен результат вызова функции books_by_subject() с аргументом аll (признак того, что пользователь хочет получить список книг по всем темам). Затем следуют результаты, полученные при вызове функции с аргументом Computers (получение списка книг, посвященных компьютерам).
Листинг 6.34. Результаты вызова функции books_by_subject()
SELECT books.books_by_subject('all');
Ответ:
Arts:
Dynamic Anatomy;
Business:
Children Books:
The Cat in the Hat;
Bartholomew and the Oobleck;
Franklin in the Dark;
Goodnight Moon;
. . . . . . . . . . . . . . .
Science Fiction:
Dune;
A Space Odyssey;
Циклы
Другую категорию команд, передающих управление внутри функций, составляют циклы. В циклах используются разные виды итераций, предназначенные для решения разных задач. Итеративные вычисления значительно расширяют возможности функций PL/pgSQL.
В PL/pgSQL реализованы три типа циклов: простейший (безусловный) цикл, цикл WHILE и цикл FOR. Вероятно, из этих трех циклов чаще всего применяется цикл FOR, подходящий для широкого круга задач программирования, хотя и другие циклы также достаточно часто встречаются на практике.
Дата добавления: 2015-02-03; просмотров: 830;