Предыдущая лекция | Содержание | Следующая лекция
Программирование. Лекция №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;

В результате завершаются как помеченный цикл, так и все вложенные в него циклы.
Hosted by uCoz