Простой цикл LOOP в PL/SQL Oracle
Структура простого цикла является самой элементарной среди всех циклических конструкций. Такой цикл состоит из ключевого слова LOOP, исполняемого кода (тела цикла) и ключевых слов END LOOP:
LOOP исполняемые_команды END LOOP;
Цикл начинается командой LOOP, а заканчивается командой END LOOP. Тело цикла должно содержать как минимум одну исполняемую команду.
Свойства простого цикла
Свойство | Описание |
Условие завершения цикла | Если в теле цикла выполняется команда EXIT. В противном случае цикл выполняется бесконечно. |
Когда проверяется условие завершения цикла | В теле цикла и только при выполнении команды EXIT или EXIT WHEN. Таким образом, тело цикла (или его часть) всегда выполняется как минимум один раз. |
В каких случаях используется данный цикл | (1) Если не известно, сколько раз будет выполняться тело цикла; (2) тело цикла должно быть выполнено хотя бы один раз. |
Простой цикл удобно использовать, когда нужно гарантировать хотя бы однократное выполнение тела цикла (или хотя бы его части). Так как цикл не имеет условия, которое бы определяло, должен ли он выполняться или нет, тело цикла всегда будет выполнено хотя бы один раз.
Простой цикл завершается только в том случае, если в его теле выполняется команда EXIT (или ее «близкий родственник» — EXIT WHEN) или же в нем инициируется исключение (оставшееся необработанным).
Завершение простого цикла: EXIT и EXIT WHEN
Если вы не хотите, чтобы программа работала бесконечно, в теле цикла следует разместить команду EXIT или EXIT WHEN:
EXIT; EXIT WHEN условие;
Здесь условие — это логическое выражение.
В следующем примере команда EXIT прерывает выполнение цикла и передает управление команде, следующей за командой END LOOP. Функция account_balance возвращает остаток денег на счету с идентификатором account_id. Если на счету осталось менее 1000 долларов, выполняется команда EXIT и цикл завершается. В противном случае программа снимает с банковского счета клиента сумму, необходимую для оплаты заказов.
LOOP balance_remaining := account_balance (account_id); IF balance_remaining < 1000 THEN EXIT; ELSE apply_balance (account_id, balance_remaining); END IF; END LOOP;
Команда EXIT может использоваться только в цикле LOOP.
В PL/SQL для выхода из цикла также предусмотрена команда EXIT WHEN, предназначенная для завершения цикла с проверкой дополнительного условия. В сущности, EXIT WHEN сочетает в себе функции IF-THEN и EXIT. Приведенный пример можно переписать с использованием EXIT WHEN:
LOOP /* Вычисление баланса */ balance_remaining := account_balance (account_id); /* Условие встраивается в команду EXIT */ EXIT WHEN balance_remaining < 1000; /* Если цикл все еще выполняется, с баланса списываются средства */ apply_balance (account_id, balance_remaining); END LOOP;
Как видите, во второй форме для проверки условия завершения команда IF не нужна. Логика проверки условия встраивается в команду EXIT WHEN. Так в каких же случаях следует использовать команду EXIT WHEN, а в каких — просто EXIT?
Команда EXIT WHEN подойдет, когда условие завершения цикла определяется одним выражением. Предыдущий пример наглядно демонстрирует этот сценарий.
При нескольких условиях завершения цикла или если при выходе должно быть определено возвращаемое значение, предпочтительнее IF или CASE с EXIT.
В следующем примере удобнее использовать команду EXIT. Фрагмент кода взят из функции, сравнивающей содержимое двух файлов:
... IF (end_of_file1 AND end_of_file2) THEN retval := TRUE; EXIT; ELSIF (checkline != againstline) THEN retval := FALSE; EXIT; ELSIF (end_of_file1 OR end_of_file2) THEN retval := FALSE; EXIT; END IF; END LOOP;
Моделирование цикла REPEAT UNTIL
В PL/SQL отсутствует традиционный цикл REPEAT UNTIL, в котором условие проверяется после выполнения тела цикла (что гарантирует выполнение тела как минимум один раз). Однако этот цикл легко моделируется простым циклом следующего вида:
LOOP ... тело цикла ... EXIT WHEN логическое_условие; END LOOP;
Здесь логическое_условие — логическая переменная или выражение, результатом проверки которого является значение TRUE или FALSE (или NULL).
Бесконечный цикл
Некоторые программы рассчитаны на непрерывное выполнение с накоплением необходимой информации. В таких случаях можно намеренно использовать бесконечный цикл:
LOOP сбор_данных; END LOOP;
Но каждый программист, имевший дело с зацикливанием, подтвердит: бесконечный цикл обычно поглощает значительную часть ресурсов процессора. Проблема решается приостановкой выполнения между итерациями (и, разумеется, максимально возможной эффективностью сбора данных):
LOOP сбор_данных; DBMS_LOCK.sleep(10); -- ничего не делать в течение 10 секунд END LOOP;
Во время приостановки программа практически не расходует ресурсы процессора.