Операторы управления выполнением программы PL/SQL

Операторы условного перехода (IF …)

Существует три модификации оператора условного перехода:

IF-THEN                               |  IF-THEN-ELSIF
-------                               |  -------------
   IF условие THEN                    |     IF условие1 THEN
     последовательность команд;       |       1-я последовательность команд;
   END IF;                            |     ELSIF условие2 THEN
                                      |       2-я последовательность команд;
IF-THEN-ELSE                          |       ...
------------                          |     ELSIF условиеN THEN
   IF условие THEN                    |       N-я последовательность команд;
     1-я последовательность команд;   |   [ ELSE
   ELSE                               |       N+1-я последовательность команд; ]
     2-я последовательность команд;   |     END IF;
   END IF;                            |


Во всех модификациях если «условие» или «условие1″ истинно (TRUE), то выполняется «последовательность команд» или «1-я последовательность команд» и управление передается на первый оператор после END IF. Если же оно ложно (FALSE), то:

  • в модификации IF-THEN управление передается на первый оператор после END IF;
  • в модификации IF-THEN-ELSE выполняется 2-я последовательность команд и управление передается на первый оператор после END IF;
  • в модификации IF-THEN-ELSIF проверяется условие 2; если оно истинно, то выполняется 2-я последовательность команд и управление передается на первый оператор после END IF; если условия 1 и 2 ложны, а условие 3 истинно, то выполняется 3-я последовательность команд и управление передается на первый оператор после END IF; наконец, если условия 1, 2, …, N ложны, то выполняется N+1-я последовательность команд и управление передается на первый оператор после END IF.

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

Метки и оператор безусловного перехода (GOTO)

В любом месте программы может быть поставлена метка, имеющая синтаксис: <<имя_метки>>
Оператор GOTO позволяет осуществить безусловный переход к метке, имя которой должно быть уникальным внутри программы или блока PL/SQL. Например, управление передается вниз к помеченному оператору:

BEGIN

GOTO insert_row;

<>
INSERT INTO shtat VALUES …
END;

В следующем примере управление передается вверх к помеченной последовательности операторов:

BEGIN

<>
BEGIN
UPDATE shtat SET …

END;

GOTO update_row;

END;

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

  • в IF-блок, LOOP-блок или в другой блок, не включающий текущий;
  • из одного предложения IF-оператора к другому;
  • из внешнего блока в SUB-блок;
  • из обработчика особых ситуаций в текущий блок.

Операторы цикла (LOOP, WHILE…LOOP и FOR…LOOP)

Циклы служат для повторяемого выполнения последовательности команд. В PL/SQL используются три модификации операторов цикла: LOOP, WHILE…LOOP и FOR…LOOP.
Цикл LOOP имеет следующий синтаксис:

LOOP
последовательность команд;
END LOOP;

и приводит к бесконечному повторению последовательности команд, если внутри нее нет команд EXIT (выход из цикла), RAISE (вызов обработчика исключительных ситуаций) или GOTO (безусловный переход). Например,

LOOP
последовательность команд;
IF условие THEN EXIT;
END LOOP;

приведет к выходу из цикла после выполнения последовательности команд, как только условие станет истинным.

Цикл WHILE предназначен для повторения последовательности команд, пока условие остается истинным:

WHILE условие LOOP
последовательность команд;
END LOOP;

Наиболее распространен цикл FOR, имеющий следующий синтаксис:

FOR индекс IN [REVERSE] нижняя_граница..верхняя_граница LOOP
последовательность команд;
END LOOP;

Здесь индекс (счетчик циклов) изменяется от нижней до верхней границы с шагом 1, а при использовании «REVERSE» – от верхней до нижней границы с шагом. Например,

FOR i IN 1..3 LOOP — для i = 1, 2, 3
последовательность команд; — цикл выполняется 3 раза
END LOOP;
FOR i IN REVERSE 1..3 LOOP — для i = 3, 2, 1
последовательность команд; — цикл выполняется 3 раза
END LOOP;

Отметим, что в последнем случае пределы диапазона указываются в возрастающем, а не убывающем порядке.
Если нижняя граница равна верхней, последовательность выполняется один раз.
Если нижняя граница больше верхней, последовательность не выполняется, и управление переходит к следующему за циклом оператору.
Пределы диапазона цикла могут быть литералами, переменными или выражениями, но должны быть целыми числами. Например, допустимы следующие диапазоны:

    j IN -5..5
    k IN REVERSE first..last
    step IN 0..TRUNC(high/low) * 2
    code IN ASCII('A')..ASCII('J')

Объявлять индекс не нужно – он объявлен неявно как локальная переменная типа integer.
PL/SQL позволяет определять диапазон цикла динамически во время выполнения. Например:

SELECT COUNT(otdel) INTO shtat_count FROM shtat;
FOR i IN 1..shtat_count LOOP

END LOOP;

Значение «shtat_count» – неизвестно во времени компиляции; предложение SELECT определяет это значение во время выполнения.
Индекс может использоваться в выражениях внутри цикла, но не может изменяться. Например:

FOR ctr IN 1..10 LOOP

IF NOT finished THEN
INSERT INTO … VALUES (ctr, …); — правильно
factor := ctr * 2; — правильно

ELSE
ctr := 10; — неправильно
END IF;
END LOOP;

Индекс определен только внутри цикла и на него нельзя ссылаться снаружи цикла. После выполнения цикла индекс неопределен. Например:

FOR ctr IN 1..10 LOOP

END LOOP;
sum := ctr – 1; — неверно

Подобно PL/SQL блокам, циклы могут быть помечены. Метка устанавливается в начале оператора LOOP, следующим образом:

<>
LOOP
последовательность команд;
END LOOP;

Имя метки может также появляться в конце утверждения LOOP как в примере:

<>
LOOP

END LOOP my_loop;

Помеченные циклы используются для улучшения чтения программы (разборчивости). С любой формой утверждения EXIT можно завершать не только текущий цикл, но и любой внешний цикл. Для этого маркируйте внешний цикл, который надо завершить, и используйте метку в утверждении EXIT, следующим образом:

<>
LOOP

LOOP

EXIT outer WHEN … — завершаются оба цикла
END LOOP;

END LOOP outer;

Если требуется преждевременно выйти из вложенного цикла FOR, маркируйте цикл и используйте метку в утверждении EXIT. Например:

<>
FOR i IN 1..5 LOOP

FOR j IN 1..10 LOOP
FETCH s1 INTO ShRec;
EXIT outer WHEN s1%NOTFOUND; — завершаются оба цикла

END LOOP;
END LOOP outer;
– управление передается сюда

Операторы EXIT, EXIT-WHEN и NULL

EXIT используется для завершения цикла, когда дальнейшая обработка нежелательна или невозможна. Внутри цикла можно помещать один или большее
количество операторов EXIT. Имеются две формы EXIT: EXIT и EXIT-WHEN.

По оператору EXIT цикл завершается немедленно и управление переходит к следующему за END LOOP оператору. Например:

LOOP

IF … THEN

EXIT; — цикл завершается немедленно
END IF;
END LOOP;
– управление переходит сюда

По оператору EXIT-WHEN цикл завершиться только в том случае, когда становится истинным условие в предложении WHEN. Например:

LOOP
FETCH s1 INTO …
EXIT WHEN s1%NOTFOUND; — конец цикла, если условие верно

END LOOP;
CLOSE s1;

Оператор EXIT-WHEN позволяет завершать цикл преждевременно. Например, следующий цикл обычно выполняется десять раз, но как только не находится значение s1, цикл завершается независимо от того сколько раз цикл выполнился.

FOR j IN 1..10 LOOP
FETCH s1 INTO ShRec;
EXIT WHEN s1%NOTFOUND; — выход при отсутствии возвращаемой строки

END LOOP;

NULL – пустой оператор; он передает управление к следующему за ним оператору.
Однако, к нему может передаваться управление и его наличие часто улучшает читаемость программы. Он также полезен для создания фиктивных подпрограмм для резервирования областей определения функций и процедур при отладке программ.

Оставить комментарий