Предыдущая лекция
|
Содержание
|
Следующая лекция
Программирование. Лекция №5. PL/SQL.
Знаковое множество.
Программа на PL/SQL представляет собой набор текстовых строк, записанных с использованием
определенного множества знаков. Знаковое множество PL/SQL включает:
o прописные и строчные буквы латинского алфавита А .. Z, а .. z;
o цифры 0 ..9;
o табулятор, пробел, возврат каретки;
o символы () + - * / > < = ! ~ ; : . ' @ % , " # $ ^ & _ | {} ? []
PL/SQL не учитывает различия между буквами верхнего и нижнего регистров, поэтому буквы
нижнего регистра эквивалентны соответствующим буквам верхнего регистра, кроме случаев их
употребления в строковых и символьных литералах.
Лексемы.
Строка исходного текста PL/SQL состоит из символьных цепочек, называемых лексемами, которые
можно разбить на следующие классы:
o ограничители (простые и составные символы);
o идентификаторы, которые включают зарезервированные слова;
o литералы;
o комментарии.
Например, строка
bonus := salary * 0.10; -- расчет премиальных содержит следующие лексемы:
o идентификаторы bonus и salary
o составной символ-ограничитель :=
o простые символы-ограничители * и ;
o числовой литерал 0.10
o комментарий -- расчет премиальных
Для облегчения восприятия лексемы можно разделять пробелами. Смежные идентификаторы
обязательно должны разделяться пробелами или ограничителем.
Однако нельзя включать пробелы в лексемы, не являющиеся строковыми литералами или
комментариями. Например, нельзя расщепить составной символ присваивания (:=).
Ограничители.
Ограничитель - это простой или составной символ, который имеет специальное значение
в PL/SQL. Например, ограничители используются для обозначения арифметических операций:
сложения, вычитания и др.
Простые символы
Простой символ представляет собой один знак; ниже приводится список простых символов.
+ операция сложения
- операция вычитания или унарный минус
* операция умножения
/ операция деления
= операция отношения
> операция отношения
< операция отношения
( левый ограничитель выражения или списка
) правый ограничитель выражения или списка
; символ завершения оператора
% признак атрибута
, разделитель элементов в списке
. селектор компонента
@ признак удаленного доступа
' ограничитель строки символов
" ограничитель идентификатора в кавычках
: признак переменной базового языка
Составные символы
Составные символы состоят из двух знаков; ниже приводится их список.
** операция возведения в степень
<> операция отношения
! = операция отношения
~= операция отношения
^= операция отношения
>= операция отношения
<= операция отношения
: = операция присваивания
=> операция связывания
.. операция диапазона
|| операция конкатенации
<< левый ограничитель метки
>> правый ограничитель метки
-- признак однострочного комментария
/* левый ограничитель многострочного комментария
*/ правый ограничитель многострочного комментария
Идентификаторы.
Идентификаторы используются в PL/SQL для именования программных объектов и модулей, которые
включают константы, переменные, исключения, курсоры, курсорные переменные, подпрограммы
и пакеты. Ниже приводится несколько примеров.
X
t2
phone#
credit_limit
LastName
oracle$number
Идентификатор начинается с буквы, за которой могут следовать буквы, цифры, знаки доллара,
подчеркивания или номера (#). Другие знаки, например, дефис, наклонная черта, пробел, -
запрещены, как показано в следующих примерах:
mine&yours -- запрещенный амперсанд
debit-amount -- запрещенный дефис
on/off -- запрещенная наклонная черта
user id -- запрещенный пробел
Следующие примеры показывают, что знак доллара, подчеркивания или номера может встречаться
несколько раз подряд или быть завершающим знаком в идентификаторе:
money$$$tree
SN##
try_again_
В идентификаторах могут использоваться и прописные, и строчные буквы в произвольном порядке.
PL/SQL не учитывает регистр букв, кроме случаев их употребления в строковых и символьных
литералах. Таким образом, если идентификаторы различаются лишь регистром соответствующих
букв, PL/SQL будет считать их одинаковыми, как показывает следующий пример:
lastname
LastName - то же, что и lastname
LASTNAME -- то же, что и lastname, а также LastName
Идентификатор не может быть длиннее 30 символов. При этом учитывается каждый символ,
включая знаки доллара, подчеркивания и номера. Например, PL/SQL считает различными следующие
идентификаторы:
lastname
last_name
Идентификаторы должны быть содержательными. Поэтому избегайте таких непонятных сокращений,
как срт. Используйте имена, имеющие смысл, например, cost.per.thousand.
Зарезервированные слова
Некоторые идентификаторы, называемые зарезервированными словами,имеют специальное назначение
в синтаксисе PL/SQL и не могут быть переопределены. Например, слова BEGIN И END, которые
обрамляют исполняемый раздел блока или подпрограммы, вляются зарезервированными. Как
показано в следующем примере, если вы попытаетесь переопределить зарезервированное слово,
то получите сообщение об ошибке компиляции.
DECLARE
end BOOLEAN; - неправильно: вызовет ошибку компиляции
Зарезервированное слово, однако, может быть частью идентификатора, как показывает
следующий пример:
DECLARE
end_of_game BOOLEAN; - допустимо
Часто зарезервированные слова записываются прописными буквами, чтобы они четко выделялись
при чтении. Однако, как и другие идентификаторы в PL/SQL, эти слова могут быть записаны
строчными буквами или включать и прописные, и строчные буквы в произвольном порядке.
Идентификаторы в кавычках
В дополнение к обычным идентификаторам, PL/SQL предоставляет возможность использовать
идентификаторы, заключенные в двойные кавычки. Необходимость в таких идентификаторах
возникает редко, но иногда они могут оказаться полезными. Они могут содержать любую
цепочку воспроизводимых при печати символов, включая пробелы, но исключая двойные кавычки.
Так, следующие идентификаторы вполне допустимы:
"X+Y"
"last name"
"on/off switch"
"employee(s)"
"*** header info ***"
Максимальная длина идентификатора в кавычках составляет 30 символов, не считая самих кавычек.
В качестве идентификаторов в кавычках можно использовать и зарезервированные слова PL/SQL,
но это считается плохим стилем программирования.
Некоторые зарезервированные слова PL/SQL не являются таковыми в SQL. Например,
зарезервированное в PL/SQL слово TYPE может быть использовано в команде CREATE TABLE
В качестве имени столбца базы данных. Однако, если команда SQL в вашей программе
обратится к этому столбцу, вы получите сообщение об ошибке компиляции, как показывает
следующий пример:
SELECT acct, type, bal INTO ... - вызовет ошибку компиляции
Эту ошибку можно исправить, заключив в кавычки записанное прописными буквами имя столбца,
как показано ниже:
SELECT acct, "TYPE", bal INTO ...
Имя столбца не может быть записано строчными буквами или включать буквы разных регистров
(если, конечно, оно не было именно так определено в команде create table при помощи двойных
кавычек). Например, следующая команда является неправильной:
SELECT acct, "type", bal INTO ... - вызовет ошибку компиляции
Другой способ - создать представление, в котором злополучный столбец
переименовывается, и в последующих командах SQL использовать представление вместо
основной таблицы.
Литералы.
Литерал - это явно заданное числовое, символьное, строковое или булево значение, не
обозначенное идентификатором. В качестве примеров можно привести числовой литерал 147 и булев
литерал false.
Числовые литералы в арифметических выражениях
Могут быть использованы два типа числовых литералов: целые и действительные.
Целочисленный литерал - это целое число без десятичной точки, возможно, со знаком.
Примеры записи целочисленных литералов:
030 6 -14 0 +32767
Действительный числовой литерал - это целое или дробное число с десятичной точкой и,
возможно, со знаком.
Примеры записи действительных числовых литералов:
6.6667 0.0 -12.0 3.14159 +8300.00 .5 25.
Такие числа, как 12.0 и 25., в PL/SQL рассматриваются как действительные, хотя они и имеют
целочисленные значения.
Числовые литералы не могут содержать знаков доллара или запятых, но могут быть записаны в
математической нотации. Число может заканчиваться буквой Е (или е), за которой сразу же
следует целое число с возможным знаком.
Примеры числовых литералов в математической нотации:
2Е5 1.0Е-7 3.14159е0 -1Е38 -9.5е-3
Букву Е здесь следует читать как "умножить на десять в степени". Другими словами, число
после буквы Е - это степень десяти, на которую надо умножить число перед буквой Е,
что иллюстрируется следующим примером (** - это операция возведения в степень):
5ЕЗ = 5 * 10**3 = 5 * 1000 = 5000
Число после буквы Е можно интерпретировать также как число разрядов, на которое нужно сдвинуть
десятичную точку. В предыдущем примере подразумеваемая десятичная точка была сдвинута
на три разряда вправо; в следующем примере она сдвигается на три разряда влево:
5Е-3 = 5*10**-3 = 5 * 0.001 = 0.005
Символьные литералы
Символьный литерал - это отдельный символ, заключенный в апострофы. Примеры символьных
литералов
'Z' '%' '7' ' ' 'z' '('
Символьный литерал может включать любой воспроизводимый при печати символ из знакового
множества PL/SQL: букву, цифру, пробел или специальный символ.
В символьных литералах PL/SQL различает буквы верхнего и нижнего регистров. Например,
литералы 'z' и 'Z' PL/SQL будет считать различными.
Символьные литералы '0'..'9' не являются эквивалентом соответствующих целочисленных литералов,
тем не менее, эти символьные литералы можно использовать в арифметических выражениях,
поскольку они могут быть неявно преобразованы в целые числа.
Строковые литералы
Символьное значение может быть обозначено идентификатором или же явно записано как
строковый литерал, т.е. как цепочка из нуля или нескольких символов, заключенная в
апострофы. Примеры строковых литералов:
'Hello, world!'
'Здравствуй, мир!'
'10-NOV-91'
'Не said "Life is like licking honey from a thorn."'
'$1,000,000'
Все строковые литералы, кроме пустой строки (''), принадлежат к типу CHAR.
Если апострофы ограничивают строковые литералы, то как изобразить в строке сам апостроф?
Как показывает следующий пример, нужно записать его два раза подряд (но это не двойные
кавычки):
'Don''t leave without saving your work.'
В строковых литералах PL/SQL различает буквы верхнего и нижнего регистров. Например,
следующие литералы считаются различными:
'baker'
'Baker'
Булевы литералы
Булевы литералы - это предопределенные значения TRUE И FALSE, a также пустое
значение NULL, которое применяется в случаях, когда настоящее значение отсутствует,
неизвестно или неприменимо. Имейте в виду, что булевы литералы - это значения сами по
себе, а не символьные строки. Например, TRUE является значением в той же мере, что и
число 25.
Комментарии.
Компилятор PL/SQL игнорирует комментарии, но вам не стоит этого делать. Добавление комментариев
в вашу программу делает ее более понятной и легкой для чтения. Вообще говоря, комментарии
должны описывать назначение и возможное применение каждого участка программы. PL/SQL
поддерживает два стиля комментирования: однострочный и многострочный.
Однострочный комментарий
Однострочный комментарий начинается двойным дефисом (--) где-нибудь в строке и продолжается
до конца строки. Примеры однострочных комментариев:
-- начало обработки
SELECT sal INTO salary FROM emp -- выборка текущего оклада
WHERE empno = emp_id;
bonus := salary * 0.15; -- расчет премиальных
Обратите внимание, что комментарий можно встроить внутрь оператора, разместив его в конце
строки.
При тестировании или отладке вам может понадобиться отключить действия в строке программы.
Следующий пример показывает, как можно "закомментировать" строку:
-- DELETE FROM emp WHERE comm IS NULL;
Многострочный комментарий
Многострочный комментарий начинается с комбинации знаков (/*), заканчивается знаками (* /)
и может занимать любое число строк. Примеры многострочных комментариев:
BEGIN
/* Начисление 15%-ной премии лучшим сотрудникам. */
IF rating > 90 THEN
bonus := salary * 0.15 /* размер премии
зависит от оклада */
ELSE
bonus := 0; END IF;
/* Следующий оператор вычисляет площадь круга, используя число пи, которое выражает
отношение длины окружности к диаметру. */
area := pi * radius**2;
Используя ограничители многострочного комментария, можно закомментировать целый участок
программы, как показывает следующий пример:
/*
LOOP
FETCH c1 INTO emp_rec;
EXIT WHEN c1%NOTFOUND;
…
END LOOP
*/
Ограничения
Вложенные комментарии не допускаются. Не разрешается также использовать однострочные
комментарии в блоке PL/SQL, который будет динамически обрабатываться программой для
предкомпилятора Oracle, где символы "конец-строки" игнорируются. В результате однострочный
комментарий захватит не только оставшуюся часть строки, но и продолжится до конца блока.
В таких ситуациях используйте многострочный комментарий.
Выражения и сравнения.
Выражения строятся из операндов и операций.
Операнд - это переменная, константа, литерал или же вызов функции, результат которой
участвует в выражении. Пример простого арифметического выражения:
-X / 2 + 3
Унарные операции, например, операция "унарный минус" (-), производят действия над одним
операндом; бинарные операции, такие, как операция деления (/), выполняют действия над
двумя операндами. Тернарных операций в PL/SQL нет.
В простейшей форме выражение состоит из единственной переменной, которая предоставляет свое
значение непосредственно. PL/SQL вычисляет выражение (находит его текущее значение), применяя
указанные операции в определенном порядке к значениям операндов. Вычисление выражения всегда
приводит к однозначному результату, принадлежащему к некоторому типу данных. PL/SQL
определяет тип данных, анализируя выражение и контекст, в котором оно появляется.
Старшинство операций
Операции в выражении выполняются в определенном порядке, в зависимости от их старшинства
(приоритета). В таблице приведен установленный по умолчанию порядок выполнения операций,
которые отсортированы здесь по убыванию приоритета (в первой строке указаны наиболее
приоритетные операции).
Операция |
Смысл |
**, NOT |
возведение в степень, логическое отрицание |
+, - |
унарный плюс, унарный минус |
*, / |
умножение, деление |
+, -, || |
сложение, вычитание, конкатенация |
=, !=, <, >, <=, >=, IS NULL, LIKE, BETWEEN, IN |
сравнение |
AND |
логическое И |
OR |
логическое ИЛИ |
Операции с более высоким старшинством применяются первыми. Например, результатом вычисления
обоих выражений, приведенных ниже, будет значение 8, поскольку деление выше по старшинству,
чем сложение:
5+12/4 12/4+5
Порядок применения операций с одинаковым старшинством в PL/SQL не установлен.
Управлять последовательностью вычислений можно при помощи скобок. Например, значением
следующего выражения будет 7, а не 11, поскольку скобки изменяют порядок вычислений,
определяемый по умолчанию старшинством операций.
(8 + 6) / 2
Следующий пример показывает, что скобками всегда можно воспользоваться для большей
выразительности, даже если в них нет необходимости:
(salary * 0.05) + (commission * 0.25)
Логические операции
Логические операции AND, OR И NOT подчиняются трехзначной логике, и результат их применения
определяется таблицами истинности, приведенными в таблице. Операции AND и OR - бинарные, a
NOT - унарная.
X У xANDy xORy NOTx
TRUE TRUE TRUE TRUE FALSE
TRUE FALSE FALSE TRUE
TRUE NULL NULL TRUE
FALSE TRUE FALSE TRUE TRUE
FALSE FALSE FALSE FALSE
FALSE NULL FALSE NULL
NULL TRUE NULL TRUE NULL
NULL FALSE FALSE NULL
NULL NULL NULL NULL
Как показано в таблицах истинности, AND возвращает значение TRUE только в том случае,
когда истинны оба операнда. С другой стороны, OR возвращает значение TRUE, когда истинным
является хотя бы один из операндов, NOT возвращает значение, противоположное своему
операнду (логическое отрицание). Например, NOT TRUE возвращает FALSE.
NOT NULL возвращает NULL, поскольку NULL - это неопределенное значение. Другими словами,
результат применения операции NOT к неопределенному значению будет также неопределенным.
Необходимо всегда внимательно относиться к выражениям, которые могут включать неопределенные
операнды. Значения NULL могут стать причиной неожиданных результатов: см. раздел
"Значения NULL в выражениях".
Порядок операций
Если для указания порядка операций не использованы скобки, порядок определяется старшинством
операций. Сравните следующие выражения:
NOT (valid AND done) и NOT valid AND done
Если обе булевы переменные valid и done имеют значение FALSE, первое выражение примет
значение TRUE. Однако результатом второго выражения будет FALSE, так как NOT по старшинству
выше, чем AND; поэтому второе выражение эквивалентно выражению
(NOT valid) AND done
Следующий пример примечателен тем, что если valid имеет значение FALSE, то результатом всего
выражения будет FALSE, независимо от значения done:
valid AND done
Аналогичное рассуждение применимо к следующему примеру: если valid имеет значение
TRUE, все выражение принимает значение TRUE, независимо от значения done:
valid OR done
Вычисление по краткой схеме
Обрабатывая булево выражение, PL/SQL применяет вычисление по краткой схеме. Другими словами,
PL/SQL прекращает вычисление булева выражения в тот же момент, когда становится известным
окончательный результат. При этом некоторые части выражения могут остаться невычисленными,
что позволяет строить такие выражения, которые при полном вычислении могли бы
привести к ошибке. Рассмотрим следующее выражение с операцией OR:
DECLARE
…
on_hand INTEGER;
on_order INTEGER;
BEGIN
IF (on_hand = 0) OR (on_order / on_hand < 5) THEN
END IF;
END;
Если значение on-hand равно нулю, левый операнд OR принимает значение TRUE, и условие в
операторе IF ИСТИННО, независимо от значения правого операнда, поэтому PL/SQL его и не
вычисляет. Если бы PL/SQL попытался получить значения обоих операндов до применения
операции OR, то при вычислении правого операнда возникла бы ошибка из-за деления
на ноль. Вместе с тем необходимо заметить, что полагаться на вычисления по краткой
схеме во всех случаях - это плохой стиль программирования, приводящий к
ненадежным программам.
Операции сравнения
Операции сравнения производят сравнение одного выражения с другим. Результатом сравнения
всегда будет одно из значений TRUE, FALSE или NULL. Чаще всего операции сравнения
применяются во фразе WHERE команд манипулирования данными языка SQL и в условных
операторах управления потоком вычислений.
Операции отношения
Операции отношения позволяют сравнивать выражения произвольной сложности. В приведенной ниже
таблице поясняется смысл каждой операции.
Операция Смысл
= равно
<>, !=, ~= не равно
< меньше
> больше
<= меньше или равно
>= больше или равно
Операции IS NULL, LIKE, BETWEEN, IN также являются операциями отношения.
Операция конкатенации
Две вертикальные черты (||) обозначают операцию конкатенации, которая присоединяет одну
строку к другой, как показывает следующий пример:
'suit' || 'case' = 'suitcase'
Если оба операнда принадлежат к типу CHAR, операция конкатенации вернет значение типа
CHAR. В противном случае ее результатом будет значение типа VARCHAR.
Встроенные функции.
В PL/SQL существует весьма богатый набор встроенных функций, обеспечивающих мощные возможности
манипулирования данными. Встроенные функции можно разбить на следующие категории:
o функции регистрации ошибок;
o числовые (или математические) функции;
o символьные функции;
o функции преобразования;
o функции работы с датами;
o смешанные функции.
Таблица содержит список всех числовых и симфольных функций, распределенных по категориям.
Числовые Назначение Символьные Назначение
ABS Модуль ASCII ASCII - код
ACOS Арккосинус CONCAT Конкатенация строк
ASIN Арксинус LENGTH Длина строки
ATAN Арктангенс LOWER Перевод вимволов в нижний регистр
COS Косинус REPLACE Замена одного символа другим
COSH Гиперболический косинус SUBSTR Подстрока
EXP Экспонента UPPER Перевод символов в верхний регистр
LN Натуральный логарифм
LOG Логарифм
MOD Остаток от деления
POWER Везведение в степень
SIN Синус
SINH Гиперболический синус
SQRT Корень квадратный
TAN Тангенс
TANH Гиперболический тангенс
TRUNC Целая часть от деления
Управляющие структуры.
Обзор
Из структурного программирования известно, что любая компьютерная программа может быть
построена из базовых управляющих структур, показанных на рисунке. Для решения поставленной
задачи вы можете использовать их в любой комбинации.
Выбор (Условная конструкция) Цикл Последовательность
> > >
Выбирающая структура проверяет условие, затем выполняет ту или иную последовательность
операторов в зависимости от того, истинно или ложно условие. Условие - это любая переменная
или выражение, которые вырабатывают булево значение (TRUE ИЛИ FALSE). Циклическая структура
повторяет выполнение последовательности операторов до тех пор, пока условие остается истинным.
Последовательная структура просто выполняет последовательность операторов в том порядке,
в котором они встречаются.
Условное выполнение: оператор IF
Часто в силу различных обстоятельств приходится предпринимать альтернативные действия.
Оператор IF позволяет выполнять последовательность операторов условно. Это означает,
что от значения условия зависит, будет ли выполняться последовательность. Существует
три формы оператора IF: IF-THEN, IF-THEN-ELSE И IF-THEN-ELSIF.
IF-THEN
Простейшая форма оператора if связывает условие с последовательностью операторов, заключенной
между ключевыми словами then и end if (но не endif), следующим образом:
IF условие THEN
последовательность_операторов;
END IF;
Последовательность операторов выполняется только в том случае, если значением условия
является true. Если же его значение false или null, то оператор if ничего не делает.
В любом случае управление передается следующему оператору. Например:
IF sales > quota THEN
compute_bonus(empid);
UPDATE payroll SET pay = pay + bonus WHERE empno = emp_id
END IF;
При желании короткий оператор if можно разместить в одной строке, например:
IF х > у THEN highх; END IF;
IF-THEN-ELSE
В этой форме оператора if добавлено ключевое слово else, за которым следует альтернативная
последовательность операторов:
IF условие THEN
последовательность_операторов1;
ELSE
последовательность_операторов2;
END IF;
Последовательность операторов во фразе else выполняется только в том случае, если условие
имеет значение false или null. Таким образом, фраза else гарантирует, что какая-нибудь
последовательность операторов обязательно выполнится. В следующем примере выполняется
первая или вторая из команд update в зависимости от того, истинно или ложно условие:
IF trans_type = 'CR' THEN
UPDATE accounts SET balance = balance + credit
WHERE ...
ELSE
UPDATE accounts SET balance = balance - debit
WHERE ...
END IF;
IF-THEN-ELSIF
Фразы THEN и ELSE могут сами включать оператор IF, т.е. оператор IF может быть вложенным:
IF trans_type = 'CR' THEN
UPDATE accounts SET balance = balance + credit
WHERE ...
ELSE
IF new_balance = minimum_balance THEN
UPDATE accounts SET balance = balance - debit
WHERE ...
ELSE
RAISE insufficient_funds;
END IF;
END IF;
Иногда возникает необходимость выбрать действие из нескольких взаимоисключающих альтернатив.
Третья форма оператора IF использует ключевое слово ELSIF (НО не ELSEIF), чтобы включить
дополнительные условия, например:
IF условие1 THEN
последовательность_операторов1;
ELSIF условие2 THEN
последовательность_операторов2;
ELSE
последовательность_операторовЗ;
END IF;
Если первое условие имеет значение FALSE ИЛИ NULL, то фраза ELSIF проверяет другое условие.
Оператор IF может иметь любое число фраз ELSIF, причем заключительная фраза ELSE не является
обязательной. Значения условий вычисляются одно за другим сверху вниз. Если какое-то
условие примет значение TRUE, TO связанная с ним последовательность операторов выполняется,
и управление передается следующему оператору. Если все условия при вычислении выработали FALSE
или NULL, то выполняется последовательность во фразе ELSE. Рассмотрим пример:
BEGIN
IF sales > 50000 THEN
bonus := 1500;
ELSIF sales > 35000 THEN
bonus := 500;
ELSE
bonus := 100;
END IF;
INSERT INTO payroll VALUES (emp_id, bonus, ...);
END;
Если значение sales больше 50000, то истинны сразу два условия: первое и второе. Тем не
менее переменной bonus будет присвоено правильное значение, равное 1500, потому что в этом
случае второе условие никогда не будет проверяться. Как только первое условие примет
значение TRUE, связанный с ним оператор выполнится, и управление сразу же будет передано
на команду INSERT.
Рекомендации
1. Следует избегать в операторе IF неуклюжих конструкций наподобие тех, что встречаются в
следующем примере:
DECLARE
overdrawn BOOLEAN;
BEGIN
IF new_balance < minimum_balance THEN
overdrawn := TRUE;
ELSE
overdrawn := FALSE;
END IF;
IF overdrawn = TRUE THEN
RAISE insufficient_funds;
END IF;
END;
В этом фрагменте программы игнорируются два полезных обстоятельства. Первое - значение булева
рыражения может быть прямо присвоено булевой переменной. Поэтому первый оператор IF может
быть полностью заменен простым присваиванием:
overdrawn := new_balance < minimum_balance;
Второе - булева переменная сама по себе либо истинна, либо ложна. Поэтому можно следующим
образом упростить условие во втором операторе IF:
IF overdrawn THEN ...
2. Где возможно, вместо вложенного оператора IF применяйте фразу ELSIF. Это облегчает чтение
и понимание текста программы. Сравните следующие две записи оператора IF:
IF условие1 THEN
Оператор1;
ELSE
IF условие2 THEN
Оператор2;
ELSE
IF условиеЗ THEN
ОператорЗ;
END IF;
END IF;
END IF;
IF условие1 THEN
Оператор1;
ELSIF условие2 THEN
Оператор2;
ELSIF условие3 THEN
ОператорЗ;
END IF;
По своему действию эти операторы эквивалентны, но в первом операторе логика выглядит
невразумительной, а во втором она четко прослеживается.
Циклы: операторы LOOP и EXIT
LOOP
Оператор LOOP позволяет многократно выполнить последовательность операторов. Существует три
формы оператора LOOP: LOOP, WHILE-LOOP и FOR-LOOP.
Простейшая форма оператора LOOP представляет собой примитивный (или бесконечный) цикл, в
котором между ключевыми словами LOOP И END LOOP включается последовательность
операторов:
LOOP
последовательноеть_операторов;
END LOOP;
При каждом повторении цикла выполняется последовательность операторов, затем происходит
возврат к началу цикла. Если дальнейшая обработка нежелательна или невозможна, то для
завершения цикла можно использовать оператор EXIT. Оператор EXIT может быть размещен в
любом месте внутри цикла, но вне цикла его применение недопустимо. Существует две формы
оператора EXIT: EXIT И EXIT-WHEN.
WHILE-LOOP
Оператор while-loop связывает условие с последовательностью операторов, заключенной между
ключевыми словами loop и end loop, как показано ниже:
WHILE условие LOOP
последовательноеть_операторов;
END LOOP;
Перед каждым повторением цикла вычисляется условие. Если его значением является true,
последовательность операторов выполняется, затем управление передается на начало цикла.
Если значением условия является false или null, то цикл обходится, и управление передается
следующему оператору.
Ниже следует пример:
WHILE total <= 25000 LOOP
SELECT sal INTO salary FROM emp
WHERE ... total := total + salary;
END LOOP;
Число повторений зависит от условия и неизвестно до окончания цикла. Так как условие
проверяется в начале цикла, число выполнений последовательности может оказаться и нулевым.
Если в предыдущем примере начальное значение total больше 25000, то условие сразу примет
значение false, и цикл будет пропущен.
В некоторых языках имеются конструкции loop until или repeat until, которые проверяют условие
в конце цикла, а не в начале. Поэтому последовательность операторов выполняется хотя бы один
раз. В PL/SQL нет такой конструкции, но ее можно легко построить, например, так:
LOOP
последовательность_операторов;
EXIT WHEN булево_выражение;
END LOOP;
Чтобы обеспечить выполнение цикла while хотя бы один раз, можно в условии использовать
предварительно инициализированную булеву переменную, как показано
в следующем примере:
done := FALSE;
WHILE NOT done LOOP
последовательность_операторов;
done := булево_выражение;
END LOOP;
Внутри цикла должен существовать оператор, присваивающий булевой переменной новое значение.
В противном случае вы получите бесконечный цикл. Например, следующие два оператора LOOP по
своему действию эквивалентны:
WHILE TRUE LOOP
END LOOP;
LOOP
END LOOP;
FOR-LOOP
Если для цикла WHILE число повторений не известно до тех пор, пока цикл не завершится, то в
цикле FOR оно известно еще до входа в цикл. Цикл FOR повторяет свои действия для указанного
диапазона целых чисел. Этот диапазон является частью схемы повторения, которая задается между
ключевыми словами FOR и LOOP. Две точки (..) обозначают операцию диапазона. Цикл FOR имеет
следующий синтаксис:
FOR счетчик IN [REVERSE] нижняя__граница..верхняя_граница LOOP
последовательность_операторов;
END LOOP;
Границы диапазона вычисляются при первом входе в цикл и внутри цикла не изменяются.
Как показано в следующем примере, последовательность операторов выполняется по одному разу
для каждого целого числа из указанного диапазона. После каждого повторения счетчик цикла
увеличивается на 1.
FOR i IN 1..3 LOOP -- присвоить i значения 1,2,3
последовательность_операторов; -- выполняется три раза
END LOOP;
Следующий пример показывает, что если нижняя граница равна верхней, то последовательность
операторов выполняется ровно один раз:
FOR i IN 3..3 LOOP -- присвоить i значение 3
последовательность_операторов; -- выполняется один раз
END LOOP;
По умолчанию, счетчик цикла продвигается, увеличиваясь от нижней границы до верхней.
Однако, если вы употребите ключевое слово REVERSE, цикл будет выполняться с уменьшением
счетчика от верхней границы до нижней, как показано в примере ниже. После каждого повторения
счетчик цикла уменьшается на 1.
FOR i IN REVERSE 1..3 LOOP -- присвоить i значения 3,2,1
последовательность_операторов; -- выполняется три раза END LOOP;
Тем не менее границы диапазона записываются в возрастающем (а не в убывающем) порядке.
Внутри цикла значение счетчика цикла может быть использовано, как если бы это была константа.
Таким образом, счетчик цикла может участвовать в выражении, но ему нельзя присваивать
значения, как видно из следующего примера:
FOR ctr IN 1. .10 LOOP
IF NOT finished THEN
INSERT INTO ... VALUES (ctr, . . .) ; -- допустимо
factor := ctr * 2; -- допустимо ELSE
ctr := 10; -- недопустимо
END IF;
END LOOP;
EXIT
Оператор exit заставляет цикл завершиться без всяких условий. Когда встречается оператор
exit, цикл немедленно завершается, и управление передается следующему оператору.
Например:
LOOP
IF credit_rating < 3 THEN
EXIT; --немедленно выйти из цикла
END IF;
END LOOP; --отсюда возобновляется выполнение программы
Необходимо всегда помнить, что оператор exit можно использовать только внутри цикла. Если
вы хотите завершить блок PL/SQL прежде, чем будет достигнуто его нормальное окончание,
можно применять оператор return.
EXIT-WHEN
Оператор exit-when позволяет завершить цикл по условию. Когда встречается оператор exit,
вычисляется значение условия во фразе when. Если условие имеет значение true, to цикл
завершается, и управление передается первому оператору, следующему за циклом.
Например:
LOOP
FETCH cl INTO . . .
EXIT WHEN cl%NOTFOUND; -- выйти из цикла,
... -- если условие истинно
END LOOP;
CLOSE cl;
Пока условие не примет значение true, цикл завершиться не сможет. Поэтому операторы внутри
цикла должны изменять значение условия. Если в предыдущем примере оператор fetch выберет
строку, условие примет значение false. Когда оператор fetch не сможет вернуть строку,
значением условия станет true, цикл закончится, и управление будет передано оператору
close.
Оператор EXIT-WHEN может служить хорошей заменой простому оператору IF. Сравните, например,
такие операторы:
IF count > 100 THEN
EXIT;
END IF;
EXIT WHEN count > 100;
По своему действию эти операторы эквивалентны, но оператор EXIT-WHEN легче для чтения и
понимания.
Оператор EXIT позволяет досрочно завершить цикл FOR. Например, следующий цикл может
выполниться и десять раз, но если в какой-то момент оператор FETCH не сможет выбрать
строку, цикл завершится немедленно и независимо от того, сколько раз он выполнялся до
этого:
FOR j IN 1. .10 LOOP
FETCH cl INTO emp_rec;
EXIT WHEN cl%NOTFOUND;
END LOOP;
Метки циклов
Метка - необъявленный идентификатор в двойных угловых скобках - должна размещаться в
самом начале оператора LOOP, как показано в следующем примере:
<<имя_метки>>
LOOP
последовательность_операторов;
END LOOP;
Имя метки может также появиться в конце оператора LOOP, например:
<>
LOOP
…………
END LOOP my_loop;
Если вложенные циклы имеют метки, вы можете сделать текст программы более выразительным,
отметив окончание каждого цикла.
При любой форме оператора EXIT МОЖНО завершить не только текущий цикл, но и любой другой, в
который он вложен. Для этого нужно просто пометить тот внешний цикл, который вы хотите
завершить. Затем вы должны указать эту метку в операторе EXIT, как показано ниже:
"outer"
LOOP
...
LOOP
EXIT outer WHEN ... -- закончить оба цикла
END LOOP;
END LOOP outer;
В результате завершаются как помеченный цикл, так и все вложенные в него циклы.