Что такое loop в sql
Что такое loop в sql
Самый простой тип цикла в языке PL/SQL таков:
Давайте рассмотрим пример с применением цикла LOOP EXIT WHEN. Запишем следующее:
Получаем после исполнения:
Видимых действий не было, но и ошибок то же! Первый цикл закончился после того как i стало равно 10. При этом оно получило значение 0 и произошел выход из цикла. Второй цикл применил вложенное предложение EXIT WHEN, что является более верным его использованием синтаксически. Тем не менее, применение условных операторов предполагает перед выходом из цикла проделать некоторые действия. Цикл LOOP EXIT WHEN END LOOP в последующем будет самым, часто используемым при построении конструкций курсоров. Рассмотрим еще одну разновидность вышеприведенного цикла:
Здесь в отличие от предыдущего цикла, действия выполняются до тех пор пока условие истинно. Если условие ложно, то цикл прекращается. Что хорошо видно из приведенного примера. В PL/SQL в конструкциях циклов нет такого, иногда полезного, оператора как CONTINUE, вследствие того, что выражение CONTINUE зарезервировано языком PL/SQL и используется для других целей. Но такую конструкцию как CONTINUE можно эмулировать, применив цикл вида LOOP EXIT WHEN END LOOP и используя весьма не популярный, но в данном случае очень полезный оператор GOTO!
Запишем следующее, выведем все нечетные числа до 20:
В результате применения GOTO в теле цикла получаем не сложную и понятную логику работы. Теперь давайте рассмотрим, не менее полезный и очень популярный в PL/SQL цикл FOR. Он к стати очень удобен при работе с курсорами, но об этом чуть позднее. Запишем следующее:
В данный момент FOR успешно ничего не делал аж сто раз! Итак, давайте рассмотрим его чуть ближе, IN как и в операторе SELECT задает диапазон значений итерации цикла, а «..» это как вы помните так называемый «оператор диапазона»! Вот так просто и ясно. Остальное уже знакомо. Замечу так же, что переменная цикла i является переменной только для чтения. По этому шаг цикла FOR изменить принудительно нельзя! Если это необходимо, то лучше применять цикл вида LOOP EXIT WHEN END LOOP! 🙂 Теперь давайте поработаем с числами:
Та же задачка, только с циклом FOR. Да, функция MOD возвращает остаток от деления чисел, как вы, наверное, уже догадались. Так же в операторе FOR есть возможность задавать обратный отсчет, ну, например, перед стартом или взрывом! 🙂 Вот так:
Нолика не было, но бабахнуло! Вот такой достаточно богатый набор операторов циклов в языке PL/SQL! Надеюсь, вы научитесь с легкостью их применять при построении серверных приложений ваших БД! 🙂
11) Oracle PL / SQL LOOP
Что такое петли?
Циклы позволяют выполнять определенную часть кода в программе необходимое количество раз.
В этом уроке мы увидим концепцию цикла в PL / SQL и поток управления в циклах. Ты выучишь-
Введение в концепцию Loops
Концепция Loops обеспечивает следующее преимущество в кодировании.
Диаграмма ниже показывает концепцию зацикливания в графической форме
На приведенной выше диаграмме условие цикла будет проверено, и до тех пор, пока условие цикла будет выполнено, будет выполнен блок выполнения.
В каждой итерации переменная счетчика цикла, которая фактически решает условие цикла, должна изменяться, чтобы сделать выход управления из цикла. В некоторых случаях эта переменная счетчика цикла является оператором увеличения / уменьшения для предварительно определенного счетчика, а в некоторых случаях это условие поиска, которое продолжает выполнение блока до тех пор, пока он не удовлетворит его.
Loop Control Заявления
Перед изучением концепции циклов обязательно изучите операторы управления циклами. Операторы управления циклом — это операторы, которые фактически управляют потоком выполнения внутри цикла. Ниже приведено подробное описание операторов управления циклом.
ПРОДОЛЖИТЬ
Это ключевое слово отправляет механизму PL / SQL инструкцию, которая всякий раз, когда движок PL / SQL встречает это ключевое слово в цикле, пропускает оставшийся код в блоке выполнения кода, и следующая итерация начинается немедленно. Это будет в основном использоваться, если код внутри цикла хочет пропустить для определенных значений итерации.
EXIT / EXIT WHEN
Это ключевое слово отправляет механизму PL / SQL инструкцию, что всякий раз, когда ядро PL / SQL встречает это ключевое слово, оно немедленно выходит из текущего цикла. Если механизм PL / SQL встречает EXIT во вложенном цикле, то он выйдет из цикла, в котором он был определен, то есть во вложенных циклах, если EXIT во внутреннем цикле выйдет из управления только из внутреннего цикла, но не из внешней петли. «EXIT WHEN» сопровождается выражением, которое дает логический результат. Если результат равен ИСТИНА, тогда элемент управления ВЫХОДИТ.
ПЕРЕЙТИ К
Этот оператор перенесет элемент управления в помеченный оператор («GOTO ;»). Это имеет следующие ограничения
Использование этого оператора не рекомендуется, если нет других альтернатив, поскольку отслеживание контроля кода в программе будет очень затруднено из-за передачи управления из одной части в другую.
Типы циклов в PL / SQL
PL / SQL предоставляет следующие три типа циклов
Базовое утверждение цикла
Этот оператор цикла является самой простой структурой цикла в PL / SQL. Блок выполнения начинается с ключевого слова «LOOP» и заканчивается ключевым словом «END LOOP».
Условие выхода должно быть задано внутри этого исполнительного блока, чтобы управление выходило из цикла.
Для выхода из цикла необходимо явно указать ключевое слово EXIT в исполнительной части.
Синтаксис Объяснение:
Примечание. Базовый оператор цикла без ключевого слова EXIT будет бесконечным циклом, который никогда не остановится.
Пример 1 : В этом примере мы собираемся напечатать число от 1 до 5, используя базовую инструкцию цикла. Для этого мы выполним следующий код.
Объяснение кода:
Маркировка петель
В PL / SQL циклы могут быть помечены. Метка должна быть заключена между « >». Маркировка циклов, особенно в кодах вложенных циклов, обеспечит большую читабельность. Метка может быть дана в команде EXIT для выхода из этого конкретного цикла. Используя метку, можно сделать элемент управления для непосредственного выхода из внешнего цикла вложенных циклов из любого места внутри циклов, выдав команду выхода с последующей меткой внешнего цикла.
Синтаксис Объяснение:
Пример 1 : В этом примере мы собираемся напечатать число, начинающееся с 1, используя инструкцию цикла Basic. Каждое число будет напечатано столько раз, сколько его значение. Верхний предел серии фиксируется в части описания программы. Давайте узнаем, как мы можем использовать концепцию этикетки для достижения этой цели. Для этого мы выполним следующий код
Объяснение кода:
PL/SQL в Oracle Forms. Управляющие структуры. Глобальные переменные и параметры
Использование циклов
предлагаемый оператор сравнения нужно проверить на необходимость завершения выполнения операторов.
Рассмотрим пример с применением такого цикла :
Теперь рассмотрим этот же пример, только с использованием оператора EXIT-WHEN :
Из примера видно, что такая конструкция, в отличие от предыдущей, дает возможность разработчику писать менее громоздкий код.
Oracle Forms позволяет создавать циклические конструкции любого уровня вложенности. Поэтому рассмотренные нами конструкции также могут быть вложенными.
Условное управление
В вышеприведенном примере перед запуском формы будет проверено, выходной день сегодня или рабочий: если условие истинно, то есть сегодня выходной, то запретить какие-либо операции, связанные с манипуляцией данными, если же условие ложно, то в строке состояния появится сообщение: «Сегодня понедельник, удачного рабочего дня». Теперь рассмотрим пример с использованием оператора ELSE :
Рассмотрим тот же случай, только с использованием оператора ELSIF :
Как видим, построенная конструкция IF-THEN с помощью оператора ELSIF менее громоздка и более понятна.
И в заключение рассмотрим пример, в котором используются как условные, так и итеративные операторы:
Последовательное управление
Ограничения на использование GOTO
Обратите внимание, что между меткой и оператором завершения ( end ) нет исполняемого оператора, поэтому такое объявление метки вызовет ошибку. Для того чтобы избежать этой ошибки, достаточно написать ключевое слово NULL :
Оператор GOTO используется только для выхода из структуры, но не для входа в нее. Приведем пример такого объявления, все из того же программного блока:
LOOP Statements
LOOP statements execute a sequence of statements multiple times. The LOOP and END LOOP keywords enclose the statements. PL/SQL provides four kinds of loop statements: basic loop, WHILE loop, FOR loop, and cursor FOR loop. For usage information, see «Controlling Loop Iterations: LOOP and EXIT Statements».
Description of the illustration basic_loop_statement.gif
while loop statement ::=
Description of the illustration while_loop_statement.gif
for loop statement ::=
Description of the illustration for_loop_statement.gif
cursor for loop statement ::=
Description of the illustration cursor_for_loop_statement.gif
Keyword and Parameter Description
Issues a SQL query and loops through the rows in the result set. This is a convenient technique that makes processing a query as simple as reading lines of text in other programming languages.
A cursor FOR loop implicitly declares its loop index as a %ROWTYPE record, opens a cursor, repeatedly fetches rows of values from the result set into fields in the record, and closes the cursor when all rows have been processed.
An explicit cursor previously declared within the current scope. When the cursor FOR loop is entered, cursor_name cannot refer to a cursor already opened by an OPEN statement or an enclosing cursor FOR loop.
An undeclared identifier that names the loop index (sometimes called a loop counter). Its scope is the loop itself; you cannot reference the index outside the loop.
The implicit declaration of index_name overrides any other declaration outside the loop. To refer to another variable with the same name, use a label. See Example 4-15, «Using a Label for Referencing Variables Outside a Loop».
Inside a loop, the index is treated like a constant: it can appear in expressions, but cannot be assigned a value.
An optional undeclared identifier that labels a loop. label_name must be enclosed by double angle brackets and must appear at the beginning of the loop. Optionally, label_name (not enclosed in angle brackets) can also appear at the end of the loop.
You cannot reference the index of a FOR loop from a nested FOR loop if both indexes have the same name, unless the outer loop is labeled by label_name and you use dot notation. See Example 4-16, «Using Labels on Loops for Referencing».
The record is defined only inside the loop. You cannot refer to its fields outside the loop. The implicit declaration of record_name overrides any other declaration outside the loop. You cannot refer to another record with the same name inside the loop unless you qualify the reference using a block label.
Fields in the record store column values from the implicitly fetched row. The fields have the same names and datatypes as their corresponding columns. To access field values, you use dot notation, as follows:
Select-items fetched from the FOR loop cursor must have simple names or, if they are expressions, must have aliases. In the following example, wages is an alias for the select item salary+NVL(commission_pct,0)*1000 :
A query associated with an internal cursor unavailable to you. Its syntax is like that of select_into_statement without the INTO clause. See «SELECT INTO Statement». PL/SQL automatically declares, opens, fetches from, and closes the internal cursor. Because select_statement is not an independent statement, the implicit cursor SQL does not apply to it.
When you exit a cursor FOR loop, the cursor is closed automatically even if you use an EXIT or GOTO statement to exit the loop prematurely. The cursor is also closed automatically if an exception is raised inside the loop.
Циклы в PL/SQL: LOOP, FOR, WHILE и CONTINUE
Свойство | Описание |
Условие завершения цикла | Код выполняется многократно. Как остановить выполнение тела цикла? |
Когда проверяется условие завершения цикла | Когда выполняется проверка условия завершения — в начале или в конце цикла? К каким последствиям это приводит? |
В каких случаях используется данный цикл | Какие специальные факторы необходимо учитывать, если цикл подходит для вашей ситуации? |
Основы циклов языка PL/SQL
Зачем нужны три разновидности циклов? Чтобы вы могли выбрать оптимальный способ решения каждой конкретной задачи. В большинстве случаев задачу можно решить с помощью любой из трех циклических конструкций, но при неудачном выборе конструкции вам придется написать множество лишних строк программного кода, а это затруднит понимание и сопровождение написанных модулей.
Примеры разных циклов
Цикл FOR существует в двух формах: числовой и курсорной. В числовых циклах FOR программист задает начальное и конечное целочисленные значения, а PL/SQL перебирает все промежуточные значения, после чего завершает цикл:
Курсорная форма цикла FOR имеет аналогичную базовую структуру, но вместо границ числового диапазона в ней задается курсор или конструкция SELECT :
Цикл WHILE имеет много общего с простым циклом. Принципиальное отличие заключается в том, что условие завершения проверяется перед выполнением очередной итерации. Возможны ситуации, в которых тело цикла не будет выполнено ни одного раза:
Структура циклов PL/SQL
Несмотря на различия между разными формами циклических конструкций, каждый цикл состоит из двух частей: ограничителей и тела цикла.
Рис. 1. Цикл WHILE и его тело
В общем случае цикл можно рассматривать как процедуру или функцию. Его тело — своего рода «черный ящик», а условие завершения — это интерфейс «черного ящика». Код, находящийся вне цикла, ничего не должен знать о происходящем внутри него. Помните об этом при рассмотрении различных форм циклов в этой статье.
Простой цикл PL/SQL
Свойство | Описание |
Условие завершения цикла | Если в теле цикла выполняется команда EXIT. В противном случае цикл выполняется бесконечно |
Когда проверяется условие завершения цикла | В теле цикла и только при выполнении команды EXIT или EXIT WHEN. Таким образом, тело цикла (или его часть) всегда выполняется как минимум один раз |
В каких случаях используется данный цикл | (1) Если не известно, сколько раз будет выполняться тело цикла; (2) тело цикла должно быть выполнено хотя бы один раз |
Простой цикл удобно использовать, когда нужно гарантировать хотя бы однократное выполнение тела цикла (или хотя бы его части). Так как цикл не имеет условия, которое бы определяло, должен ли он выполняться или нет, тело цикла всегда будет выполнено хотя бы один раз.
Простой цикл завершается только в том случае, если в его теле выполняется команда EXIT (или ее «близкий родственник» — EXIT WHEN ) или же в нем инициируется исключение (оставшееся необработанным).
Завершение простого цикла: EXIT и EXIT WHEN
Если вы не хотите, чтобы программа «зациклилась», в теле цикла следует разместить команду EXIT или EXIT WHEN :
Здесь условие — это логическое выражение.
Моделирование цикла REPEAT UNTIL
Здесь логическое_условие — логическая переменная или выражение, результатом проверки которого является значение TRUE или FALSE (или NULL ).
Бесконечный цикл
Некоторые программы (например, средства наблюдения за состоянием системы) рассчитаны на непрерывное выполнение с накоплением необходимой информации. В таких случаях можно намеренно использовать бесконечный цикл:
Но каждый программист, имевший дело с зацикливанием, подтвердит: бесконечный цикл обычно поглощает значительную часть ресурсов процессора. Проблема решается приостановкой выполнения между итерациями (и, разумеется, максимально возможной эффективностью сбора данных):
Во время приостановки программа практически не расходует ресурсы процессора.
Цикл WHILE
Прерывание бесконечного цикла
На практике возможна ситуация, в которой бесконечный цикл потребуется завершить. Если цикл выполняется в анонимном блоке в SQL*Plus, скорее всего, проблему можно решить вводом терминальной комбинации завершения (обычно Ctrl+C). Но реальные программы чаще выполняются в виде сохраненных процедур, и даже уничтожение процесса, запустившего программу (например, SQL*Plus), не приведет к остановке фоновой задачи. Как насчет команды ALTER SYSTEM KILL SESSION? Хорошая идея, но в некоторых версиях Oracle эта команда не уничтожает зациклившиеся сеансы (почему — никто не знает). Как же «прикончить» выполняемую программу?
Использование DBMS_PIPE не оказывает заметного влияния на общую загрузку процессора.
Простая вспомогательная программа может уничтожить зациклившуюся программу, отправив по каналу сообщение « stop »:
Общий синтаксис цикла WHILE :
Свойство | Описание |
Условие завершения цикла | Если значением логического выражения цикла является FALSE или NULL |
Когда проверяется условие завершения цикла | Перед первым и каждым последующим выполнением тела цикла. Таким образом, не гарантируется даже однократное выполнение тела цикла WHILE |
В каких случаях используется данный цикл | (1) Если не известно, сколько раз будет выполняться тело цикла; (2) возможность выполнения цикла должна определяться условием; (3) тело цикла может не выполняться ни одного раза |
Условие WHILE проверяется в начале цикла и в начале каждой его итерации, перед выполнением тела цикла. Такого рода проверка имеет два важных последствия:
Цикл FOR со счетчиком
Диапазон неявно объявляет управляющую переменную цикла (если она не была явно объявлена ранее), определяет начальное и конечное значения диапазона, а также задает направление изменения счетчика (по возрастанию или по убыванию).
Общий синтаксис цикла FOR :
Между ключевыми словами LOOP и END LOOP должна стоять хотя бы одна исполняемая команда. Свойства цикла FOR с числовым счетчиком приведены в следующей таблице.
Правила для циклов FOR с числовым счетчиком
При использовании цикла FOR с числовым счетчиком необходимо следовать некоторым правилам:
Примеры циклов FOR с числовым счетчиком
Следующие примеры демонстрируют некоторые варианты синтаксиса циклов FOR с числовым счетчиком.
В этом примере количество итераций цикла определяется во время выполнения программы. Начальное и конечное значения вычисляются один раз, перед началом цикла, и затем используются в течение всего времени его выполнения.
Нетривиальные приращения
В PL/SQL не предусмотрен синтаксис задания шага приращения счетчика. Во всех разновидностях цикла FOR с числовым счетчиком значение счетчика на каждой итерации всегда увеличивается или уменьшается на единицу.
Также возможен и другой способ — умножить значение счетчика на два и использовать вдвое меньший диапазон:
В обоих случаях процедура calc_values выполняется только для четных чисел. В первом примере цикл FOR повторяется 100 раз, во втором — только 50.
Но какое бы решение вы ни выбрали, обязательно подробно его опишите. Комментарии помогут другим программистам при сопровождении вашей программы.
Цикл FOR c курсором
Цикл FOR с курсором — одна из замечательных возможностей PL/SQL, обеспечивающая тесную и эффективную интеграцию процедурных конструкций с мощью языка доступа к базам данных SQL. Его применение заметно сокращает объем кода, необходимого для выборки данных из курсора, а также уменьшает вероятность возникновения ошибок при циклической обработке данных — ведь именно циклы являются одним из основных источников ошибок в программах.
Базовый синтаксис цикла FOR с курсором:
Не объявляйте явно запись с таким же именем, как у индексной записи цикла. В этом нет необходимости, поскольку запись объявляется автоматически, к тому же это может привести к логическим ошибкам. О том, как получить доступ к информации о записях, обработанных в цикле FOR после его выполнения, рассказывается далее в этом блоге.
Мы не рекомендуем использовать эту форму, поскольку встраивание инструкций SELECT в «неожиданные» места кода затрудняет его сопровождение и отладку.
Свойства цикла FOR с использованием курсора приведены в следующей таблице.
Примеры цикла FOR с курсором
Этот код последовательно и явно выполняет все необходимые действия: мы определяем курсор (строка 2), явно объявляем запись для этого курсора (строка 5), открываем курсор (строка 7), начинаем бесконечный цикл (строка 8), производим выборку записи из курсора (строка 9), проверяем условие выхода из цикла (конец данных) по атрибуту %NOTFOUND курсора (строка 10) и, наконец, выполняем обновление (строка 11). После этого программист должен закрыть курсор (строка 14). Вот что получится, если переписать тот же код с использованием цикла FOR с курсором:
Метки циклов
Циклу можно присвоить имя при помощи метки. Метка цикла в PL/SQL имеет стандартный формат:
Метка располагается непосредственно перед командой LOOP :
Метки циклов могут пригодиться в нескольких типичных ситуациях:
Команда CONTINUE
Простой пример использования CONTINUE WHEN для пропуска итераций с четными значениями счетчика:
Команда CONTINUE чаще всего применяется для модификации существующего кода с внесением целенаправленных изменений и немедленным выходом из цикла для предотвращения побочных эффектов.
Так ли плоха команда CONTINUE?
Уже давно (еще в эпоху знаменитого манифеста Дейкстры «о вреде goto ») конструкции exit и continue были проанализированы и отнесены к структурным средствам передачи управления. Более того, команда exit была признана в одной из авторитетных работ Кнута как способ корректного прерывания вычислений.
Команда continue полезна тем, что она делает код более компактным и понятным, а также сокращает необходимость в логических переменных, смысл которых трудно понять с первого взгляда. Чаще всего она используется в циклах, в которых точная обработка каждого элемента зависит от подробных структурных тестов. Заготовка цикла может выглядеть так, как показано ниже; обратите внимание на команду exit, которая проверяет, не пора ли завершить обработку. Также стоит заметить, что последняя команда continue (после условия5) не является строго необходимой. С другой стороны, включение continue после каждого действия упрощает добавление новых действий в произвольном порядке без нарушения работоспособности других действий.
Без команды continue мне пришлось бы реализовать тело цикла следующим образом:
Также команда CONTINUE пригодится для завершения внутренних циклов и немедленного продолжения следующей итерации внешнего цикла. Для этого циклам присваиваются имена при помощи меток. Пример:
Полезные советы по работе с циклами в PL/SQL
Циклы — очень мощные и полезные конструкции, но при их использовании необходима осторожность. Именно циклы часто создают проблемы с быстродействием программ, и любая ошибка, возникшая в цикле, повторяется ввиду многократности его выполнения. Логика, определяющая условие остановки цикла, бывает очень сложной. В этом разделе приводятся несколько советов по поводу того, как сделать циклы более четкими и понятными, а также упростить их сопровождение.
Используйте понятные имена для счетчиков циклов
Как можно понять следующий ход, не говоря уже о его сопровождении?
Трудно представить, зачем использовать однобуквенные имена переменных, словно сошедшие со страниц учебника начального курса алгебры, но это происходит сплошь и рядом. Вредные привычки, приобретенные на заре эпохи программирования, искоренить невероятно сложно. А исправить этот код очень просто — достаточно присвоить переменным более информативные имена:
С содержательными именами переменных сразу видно, что внутренний цикл просто перебирает месяцы двухлетнего периода (12 × 2 = 24).
Корректно выходите из цикла
При завершении цикла следует придерживаться следующих правил:
В заголовке цикла FOR явно указано, что его тело должно быть выполнено n раз (где n — количество итераций в цикле со счетчиком или количество записей в цикле с курсором). Команда EXIT в цикле FOR (строка 12) изменяет логику его выполнения, и в результате получается код, который трудно понять и отладить.
Поэтому если нужно прервать цикл на основании информации текущей записи, лучше воспользоваться циклом WHILE или простым циклом, чтобы структура кода лучше отражала ваши намерения.
Получение информации о выполнении цикла FOR
Циклы FOR — удобные, четко формализованные структуры, которые выполняют в программе большую «административную» работу (особенно циклы с курсором). Однако у них есть и существенный недостаток: позволяя Oracle выполнять работу за нас, мы ограничиваем собственные возможности доступа к конечным результатам цикла после его завершения.
Предположим, нам нужно узнать, сколько записей обработано в цикле FOR с курсором, и затем использовать это значение в программе. Было бы очень удобно написать примерно такой код:
Команда SQL как цикл
На самом деле команда SQL (например, SELECT ) тоже может рассматриваться как цикл, потому что она определяет действие, выполняемое компилятором SQL с набором данных. В некоторых случаях при реализации определенной задачи можно даже выбрать между использованием цикла PL/SQL и команды SQL. Давайте рассмотрим пример, а затем сделаем некоторые выводы о том, какое решение лучше.
Программа работает, но является ли данное решение единственным? Конечно же, нет. Ту же логику можно реализовать с помощью команд SQL INSERT-SELECT FROM с последующей командой DELETE :
Кроме того, PL/SQL превосходит SQL в отношении гибкости. Допустим, нам хотелось бы переносить за одну операцию максимально возможное количество записей, а для тех записей, при перемещении которых произошли ошибки, просто записывать сообщения в журнал. В этом случае стоит воспользоваться циклом FOR с курсором, дополненным разделом исключений:
PL/SQL позволяет обрабатывать записи по одной и для каждой из них выполнять необходимые действия (которые могут базироваться на сложной процедурной логике, зависящей от содержимого конкретной записи). В таких случаях удобнее использовать комбинацию PL/SQL и SQL. Но если ваша задача позволяет ограничиться одним SQL, лучше им и воспользоваться — код получится и короче, и эффективнее.