Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Хранимые процедуры и функции.doc
Скачиваний:
6
Добавлен:
24.09.2019
Размер:
22.57 Mб
Скачать

1.7. Циклы

Циклы являются важнейшей конструкцией, без которой хранимые процедуры и функции не имели бы достаточно функциональности. Таблицы, как правило, имеют множество записей, поэтому циклическая обработка данных встречается в SQL-программировании достаточно часто.

Замечание! Вне хранимых процедур описываемые в данном разделе операторы применять нельзя.

1.7.1. Оператор while

Оператор while выполняет цикл и имеет следующий синтаксис:

[label:] WHILE search_condition DO

statement_list

END WHILE [label]

Цикл while выполняет операторы statement_list до тех пор, пока условие search_condition истинно. При каждой итерации условие search_condition проверяется, и если при очередной проверке оно будет ложным (0), цикл завершит сове выполнение. Это означает, что если условие search_condition ложно с самого начала, цикл не выполнит ни одной итерации.

Если в цикле требуется выполнить более одного оператора, не обязательно заключать их в блок beginend, т. к. эту функцию выполняет сам оператор while.

Выведем 3 раза текущую дату при помощи цикла while.

Первый оператор в цикле while выводит текущую дату, а второй вычитает из локальной переменной i единицу. Если единицу не вычитать, то образуется бесконечный цикл, из которого процедура никогда не выйдет, а будет бесполезно нагружать сервер, пока сеанс с ним не прекратится. Следует очень внимательно проектировать циклы, чтобы предотвратить бесконечные циклы.

В следующем примере представлен код хранимой процедуры, которая выводит текущую дату num раз, где num – параметр, задаваемый пользователем.

Как видно, цикл while снабжен меткой wet. Метка в цикле предназначена не только для того, чтобы облегчить чтение кода при очень длинных циклах, она позволяет осуществлять досрочный выход из цикла.

1.7.2. Досрочный выход из цикла

Для досрочного выхода из цикла предназначен оператор leave, который имеет следующий синтаксис:

LEAVE label

Оператор leave прекращает выполнение блока, помеченного меткой label.

Хранимая процедура nown() из вышеприведенного примера обладает недостатком – если задать очень большое значение аргумента num, можно создать псевдобесконечный цикл, который позволит злоумышленнику загрузить сервер бесполезной работой. Для предотвращения такой ситуации можно воспользоваться оператором leave, который прекратит выполнение цикла по достижении критического числа итераций. Ниже приводится пример хранимой процедуры, где число итераций ограничено двумя.

Условие if > 2 then leave wet; проверяет, не превысило ли значение счетчика i числа 2, и если это так, происходит прекращение цикла while. Использование меток позволяет точно указать, какой цикл необходимо прервать. Если имеется вложенный цикл, можно явно указать, какой из двух циклов требуется прервать (см. пример ниже).

При достижении условия i > 2 && j > 2 оператор leave прервет не вложенный цикл second, а внешний цикл first, т. к. метка внешнего цикла явно указана после оператора.

При использовании досрочного выхода leave можно даже создавать бесконечные циклы, т.к. рано или поздно внешний цикл будет завершен (см. пример ниже).

Значение 1 в условии цикла всегда будет истинным, и цикл не прекратится до тех пор, пока его не прервет оператор leave.

Еще одним оператором, выполняющим досрочное прекращение цикла, является оператор iterate, который имеет следующий синтаксис:

ITERATE label

В отличие от оператора leave, оператор iterate не прекращает выполнение цикла, он лишь выполняет досрочное прекращение текущей итерации.

Рассмотрим программу, которая в цикле формирует бинарную последовательность, добавляя к строке две единицы на четных итерациях и две единицы и два нуля на нечетных (см. пример ниже).

Бинарная последовательность хранится во временной строке bin, которая обязательно должна быть инициирована пустой строкой:

declare bin tinytext default ‘’;

Если инициализация не проведена, переменная получит значение null, и все операции с этой переменной также будут приводить к null. На каждой итерации переменной bin при помощи функции concat() прибавляется последовательность ‘11’. Если индекс i является четным (0, 2, 4, 6, 8), текущая итерация прекращается при помощи ключевого слова iterate, если индекс является нечетным (1, 3, 5, 7, 9), то итерация выполняется до конца, т. е. к временной строке bin добавляется еще и последовательность ‘00’. На четность индекс i проверяется при помощи строки

i/2 – ceiling(i/2)

Если индекс i делится на 2 без остатка, это выражение вернет 0 (ложь), если число является нечетным, то выражение вернет 0,5 (истина).