ГЛАВА 2
----------------------------------------------------------------
ОСНОВЫ
В живописи шесть главных вещей. Первая - это дух;
вторая - ритм; третья - мысль; четвертая - пейзаж;
пятая - кисть; и последняя - тушь.
Цзинь Хао
Предыдущая глава представила общие сведения о языке PL/SQL. Эта
глава фокусируется на мелких аспектах языка. Как и любой другой
язык программирования, PL/SQL имеет свое кодовое множество,
зарезервированные слова, пунктуацию, типы данных, жесткий
синтаксис, а также фиксированые правила формирования и
использования предложений. С помощью этих базовых элементов
PL/SQL вы представляете объекты и операции реального мира.
Основы 2-1
----------------
Кодовое множество
Вы пишете программу PL/SQL как строки текста, используя
специфический набор символов. В этот набор символов входят:
* прописные и строчные буквы A .. Z, a .. z
* цифры 0 .. 9
* символы табуляция, пробел и возврат каретки ("пропуски")
* символы ()+-*/<>=!~;:.'@%,"#$^&_|{}?[]
PL/SQL не различает прописных и строчных букв, и рассматривает
строчные буквы как эквиваленты соответствующих прописных букв,
исключая строковые и символьные литералы.
----------------
Лексические единицы
Строка текста программы PL/SQL распадается на группы символов,
называемые ЛЕКСИЧЕСКИМИ ЕДИНИЦАМИ, которые можно
классифицировать следующим образом:
* разделители (простые и составные символы)
* идентификаторы, в том числе зарезервированные слова
* литералы
* комментарии
Например, строка
bonus := salary * 0.10; -- вычислить премию
содержит следующие лексические единицы:
* идентификаторы bonus и salary
* составной символ :=
* простые символы * и ;
* числовой литерал 0.10
* комментарий -- вычислить премию
Для улучшения читабельности вы можете разделять лексические
единицы пропусками. На самом деле, вы обязаны разделять
соседние идентификаторы пропусками или знаками пунктуации.
Например, следующая строка незаконна, потому что
зарезервированные слова END и IF соединены:
IF x > y THEN high := x; ENDIF; -- незаконно
2-2 Руководство пользователя и справочник по PL/SQL
Однако вы не можете вставлять пропуски внутри лексических
единиц, за исключением строковых литералов и комментариев.
Например, следующая строка незаконна, потому что составной
символ для операции присваивания (:=) разъединен:
count : = count + 1; -- незаконно
Чтобы показать структуру, вы можете разбивать строки с помощью
возврата каретки и делать отступы с помощью пробелов или
табуляций. Сравните следующие предложения IF:
IF x>y THEN max:=x;ELSE max:=y;END IF; IF x > y THEN
max := x;
ELSE
max := y;
END IF;
Разделители
-----------
РАЗДЕЛИТЕЛЬ - это простой или составной символ, имеющий в PL/SQL
специальный смысл. Например, вы используете разделители для
представления арифметических операций, таких как сложение и
вычитание.
Простые символы
Простые символы кодируются как одиночные символы:
+ оператор сложения
- оператор вычитания/отрицания
* оператор умножения
/ оператор деления
= оператор сравнения
< оператор сравнения
> оператор сравнения
( ограничитель выражения или списка
) ограничитель выражения или списка
; терминатор предложения
% индикатор атрибута
, разделитель элементов
. селектор компоненты
@ индикатор удаленного доступа
' ограничитель символьной строки
" ограничитель идентификатора
: индикатор хост-переменной
Основы 2-3
Составные символы
Составные символы кодируются как пары символов:
** оператор возведения в степень
<> оператор сравнения
!= оператор сравнения
~= оператор сравнения
^= оператор сравнения
<= оператор сравнения
>= оператор сравнения
:= оператор присваивания
=> оператор ассоциации
.. оператор интервала
|| оператор конкатенации
<< ограничитель метки
>> ограничитель метки
-- индикатор однострочного комментария
/* (начальный) ограничитель многострочного комментария
*/ (конечный) ограничитель многострочного комментария
Идентификаторы
--------------
Вы используете идентификаторы для именования программных
объектов и единиц PL/SQL, к которым относятся константы,
переменные, исключения, курсоры, подпрограммы и пакеты.
Некоторые примеры идентификаторов:
X
t2
phone#
credit_limit
LastName
oracle$number
Идентификатор состоит из буквы, за которой (необязательно)
следуют одна или несколько букв, цифр, знаков доллара,
подчеркиваний или знаков номера (#). Другие символы, такие как
дефис, наклонная черта или пропуск, в идентификаторе незаконны,
как показывают следующие примеры:
mine&yours -- незаконный амперсенд
debit-amount -- незаконный дефис
on/off -- незаконная косая черта
user id -- незаконный пробел
2-4 Руководство пользователя и справочник по PL/SQL
Следующие примеры показывают, что использование в
идентификаторах знаков доллара, подчеркиваний и знаков номера
законно:
money$$$tree -- законно
SN## -- законно
try_again_ -- законно
Буквы в идентификаторах могут быть как прописными, так и
строчными. PL/SQL не различает их, за исключением строковых и
символьных литералов. Поэтому, если единственным различием
между идентификаторами является регистр соответствующих букв, то
PL/SQL трактует такие идентификаторы как одинаковые, как
показывает следующий пример:
lastname
LastName -- то же, что lastname
LASTNAME -- то же, что lastname и LastName
Длина идентификатора не может превышать 30 символов. Однако
значащим считается каждый символ в идентификаторе, включая знаки
доллара, подчеркивания и знаки номера. Например, следующие два
идентификатора считаются в PL/SQL различными:
lastname
last_name
Идентификаторы должны быть информативными. Поэтому старайтесь
использовать осмысленные имена, такие как credit_limit или
cost_per_thousand. Избегайте невразумительных имен, подобных
cr_lim или cpm.
Зарезервированные слова
Некоторые идентификаторы, называемые ЗАРЕЗЕРВИРОВАННЫМИ СЛОВАМИ,
имеют специальный смысл в PL/SQL и не могут быть переопределены.
Например, слова BEGIN и END, которые окружают исполнительную
часть блока или подпрограммы, зарезервированы. Как показывает
следующий пример, если вы попытаетесь переопределить
зарезервированное слово, вы получите ошибку компиляции:
DECLARE
end BOOLEAN; -- незаконно; вызовет ошибку компиляции
...
Однако заререзированные слова можно включать как составные части
в идентификаторы, как показывает следующий пример:
DECLARE
end_of_game BOOLEAN; -- законно
...
Как правило, зарезервированные слова пишутся прописными буквами,
чтобы облегчить читабельность. Однако это необязательно; как и
любые другие идентификаторы PL/SQL, зарезервированные слова
можно кодировать строчными или смешанными буквами. Полный
список зарезервированных слов приведен в приложении E.
Основы 2-5
Предопределенные идентификаторы
Идентификаторы, глобально объявленные в пакете STANRARD, как,
например, исключение INVALID_NUMBER, можно переобъявлять.
Однако такое переобъявление может приводить к ошибкам, потому
что глобальное объявление перекрывается вашим локальным
объявлением.
Идентификаторы в кавычках
Для большей гибкости, PL/SQL позволяет вам заключать
идентификаторы в двойные кавычки. Идентификаторы в кавычках
необходимы нечасто, но иногда они могут быть полезными. Такой
идентификатор может содержать любую последовательность печатных
символов, включая пробелы, но исключая двойные кавычки.
Следовательно, следующие идентификаторы законны:
"X+Y"
"last name"
"on/off switch"
"employee(s)"
"*** header info ***"
Максимальная длина идентификатора в кавычках составляет 30
символов, не считая кавычек.
Использование в качестве идентификаторов в кавычках
зарезервированных слов PL/SQL допускается, но НЕ рекомендуется.
Использование зарезервированных слов является плохой практикой
программирования. Однако, некоторые из зарезервированных слов
PL/SQL не являются зарезервированными в SQL. Например,
зарезервированное (в PL/SQL) слово TYPE допустимо использовать в
предложении SQL CREATE TABLE в качестве имени столбца. Однако,
если вы обратитесь к такому столбцу в предложении SQL,
содержащемся в программе PL/SQL, вы получите ошибку, как
показывает следующий пример:
SELECT acct, type, bal INTO ... -- вызовет ошибку компиляции
Чтобы предотвратить ошибку компиляции, запишите имя столбца
прописными буквами и заключите его в кавычки:
SELECT acct, "TYPE", bal INTO ...
Нельзя записывать такое имя столбца строчными буквами (если
только оно не было так закодировано в предложении CREATE TABLE).
Например, следующее предложение незаконно:
SELECT acct, "type", bal INTO ... -- вызовет ошибку компиляции
Альтернативно, вы можете создать обзор, который переименовывает
сомнительный столбец, а затем использовать этот обзор в
предложениях SQL вместо базовой таблицы.
2-6 Руководство пользователя и справочник по PL/SQL
Литералы
--------
ЛИТЕРАЛ - это явное число, символ, строка или булевское
значение, не представленное идентификатором. Примерами могут
служить числовой литерал 147 и булевский литерал FALSE.
Числовые литералы
В арифметических выражениях могут использоваться два вида
числовых литералов: целочисленные и вещественные. Целочисленный
литерал - это целое число с необязательным знаком и без
десятичной точки. Примеры целочисленных литералов:
030 6 -14 0 +32767
Вещественный литерал - это целое или дробное число с
необязательным знаком и с десятичной точкой. Примеры
вещественных литералов:
6.6667 0.0 -12.0 3.14159 +8300.00 .5 25.
PL/SQL рассматривает числа, подобные 12.0 и 25., как
вещественные, несмотря на то, что их значения по сути
целочисленны.
Числовые литералы не могут содержать знаков доллара или запятых,
но могут записываться в научной нотации. В этой нотации за
числом следует символ E (или e) и необязательное целое со
знаком. Например:
2E5 1.0E-7 3.14159e0 -1E38 -9.5e-3
Буква E означает "умножить на десять в степени". Как показывает
следующий пример, число, следующее за E, задает степень десяти,
на которую должно быть умножено число, записанное перед E:
3
5E3 = 5 x 10 = 5 x 1000 = 5000
Следовательно, число за буквой E показывает также, на сколько
мест следует передвинуть десятичную точку. В последнем примере
неявная десятичная точка сдвигалась на три позиции вправо; в
следующем примере она сдвигается на три позиции влево:
-3
5E-3 = 5 x 10 = 5 x 0.001 = 0.005
Основы 2-7
Символьные литералы
Символьный литерал - это одиночный символ, окруженный одиночными
апострофами. Примеры:
'Z' '%' '7' ' ' 'z' '('
Символьные литералы включают все печатные символы в наборе
символов PL/SQL: буквы, цифры, пропуски и специальные символы.
PL/SQL чувствителен к регистру букв в символьных литералах.
Так, литералы 'Z' и 'z' считаются различными.
Не путайте символьные литералы '0' .. '9' с числовыми
литералами. Символьные литералы нельзя использовать в
арифметических выражениях.
Строковые литералы
Символьное значение может быть представлено идентификатором или
явно записано в виде строкового литерала, который должен быть
последовательностью из нуля или более символов, заключенной в
апострофы. Ниже приведены примеры строковых литералов:
'Hello, world!'
'XYZ Corporation'
'10-NOV-91'
'He 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,
а также "не-значение" NULL, которое обозначает отсутствие,
неизвестность или неприменимость значения. Не забывайте, что
булевские литералы НЕ являются строками.
2-8 Руководство пользователя и справочник по PL/SQL
Комментарии
-----------
Компилятор 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;
Многострочные комментарии
Многострочный комментарий начинается с пары символов /* и
заканчивается парой символов */. Пример:
/* вычислить 15% премию для
сотрудников с высоким рейтингом */
IF rating > 90 THEN
bonus := salary * 0.15;
END IF;
Этот стиль позволяет, например, легко "закомментировать" секцию
блока, которую вы хотите временно исключить из выполняемого
кода, как показывает следующий пример:
/* OPEN c1;
LOOP
FETCH c1 INTO my_empno, my_ename, my_sal;
EXIT WHEN c1%NOTFOUND;
...
END LOOP;
CLOSE c1; */
Ограничения
Нельзя вкладывать комментарии друг в друга. Кроме того, нельзя
использовать однострочные комментарии в том блоке PL/SQL,
который будет обрабатываться динамически программой
прекомпилятора ORACLE, потому что в этом случае символы конца
строки игнорируются, и, как следствие, однострочный комментарий
растянется до конца блока, а не только до конца строки. Поэтому
в таких случаях используйте многострочные комментарии.
Основы 2-9
----------------
Типы данных
Каждая константа и переменная имеет ТИП ДАННЫХ, который
специфицирует ее формат хранения, ограничения и допустимый
интервал значений. PL/SQL предусматривает разнообразие
предопределенных скалярных и составных типов данных. СКАЛЯРНЫЙ
тип не имеет внутренних компонент. СОСТАВНОЙ тип имеет
внутренние компоненты, которыми можно манипулировать
индивидуально.
Рис.2-1 показывает предопределенные типы данных, которые вы
можете использовать. Еще один скалярный тип данных, MSLABEL,
доступен в Trusted ORACLE, специальной защищенной версии ORACLE.
Скалярные типы распадаются на семейства числовых, символьных,
календарных и булевских данных.
Рис.2-1
Предопределенные типы данных
---------------------------------------------------------------¬
¦ ¦
¦ Типы данных PL/SQL ¦
¦ ¦
¦ -------------------------------------¬ ---------------------¬¦
¦ ¦ Скалярные типы ¦ ¦ Составные типы ¦¦
¦ ¦ -------------------¬ ------------¬ ¦ ¦---------¬ --------¬¦¦
¦ ¦ ¦ BINARY_INTEGER ¦ ¦ CHAR ¦ ¦ ¦¦ RECORD ¦ ¦ TABLE ¦¦¦
¦ ¦ ¦ DEC ¦ ¦ CHARACTER ¦ ¦ ¦L--------- L--------¦¦
¦ ¦ ¦ DECIMAL ¦ ¦ LONG ¦ ¦ ¦ ¦¦
¦ ¦ ¦ DOUBLE PRECISION ¦ ¦ LONG RAW ¦ ¦ L---------------------¦
¦ ¦ ¦ FLOAT ¦ ¦ RAW ¦ ¦ ¦
¦ ¦ ¦ INT ¦ ¦ ROWID ¦ ¦ ¦
¦ ¦ ¦ INTEGER ¦ ¦ STRING ¦ ¦ ¦
¦ ¦ ¦ NATURAL ¦ ¦ VARCHAR ¦ ¦ ¦
¦ ¦ ¦ NUMBER ¦ ¦ VARCHAR2 ¦ ¦ ¦
¦ ¦ ¦ NUMERIC ¦ L------------ ¦ ¦
¦ ¦ ¦ POSITIVE ¦ -------¬ ¦ ¦
¦ ¦ ¦ REAL ¦ ¦ DATE ¦ ¦ ¦
¦ ¦ ¦ SMALLINT ¦ L------- ¦ ¦
¦ ¦ L------------------- ----------¬ ¦ ¦
¦ ¦ ¦ BOOLEAN ¦ ¦ ¦
¦ ¦ L---------- ¦ ¦
¦ L------------------------------------- ¦
L---------------------------------------------------------------
В этом разделе описываются скалярные типы; составные типы данных
обсуждаются в этой главе позже.
2-10 Руководство пользователя и справочник по PL/SQL
BINARY_INTEGER
--------------
Вы используете тип данных BINARY_INTEGER для хранения целых
чисел со знаком. Интервал допустимых значений для этого типа -
от -2**31 -1 до 2**31 -1 (-2147483647 .. 2147483647). PL/SQL
представляет значения BINARY_INTEGER как знаковые двоичные
числа, которые, в отличие от значений типа NUMBER, могут
использоваться в вычислениях без преобразования. Поэтому
применение переменных BINARY_INTEGER может резко увеличить
производительность.
Подтипы BINARY_INTEGER
ПОДТИП ассоциирует базовый тип с ограничением, и потому
определяет подмножество значений базового типа. Для удобства
PL/SQL имеет следующие предопределенные подтипы типа
BINARY_INTEGER:
* NATURAL (0 .. 2147483647)
* POSITIVE (1 .. 2147483647)
Вы можете использовать подтипы NATURAL или POSITIVE, если хотите
ограничить переменную неотрицательными целыми значениями.
NUMBER
------
Вы используете тип данных NUMBER для хранения чисел с
фиксированой или плавающей точкой практически любого размера.
Вы можете специфицировать ТОЧНОСТЬ, т.е. общее число цифр, и
МАСШТАБ, который определяет место округления. Синтаксис имеет
следующий вид:
NUMBER[(точность, масштаб)]
Для спецификации точности и масштаба нельзя использовать
константы или переменные; вы должны использовать целочисленные
литералы.
Максимальная точность значения NUMBER равна 38; диапазон
допустимых значений - от 1.0E-129 до 9.99E125. Если вы не
специфицируете точность, она принимает по умолчанию максимальное
значение, поддерживаемое вашей системой.
Масштаб может варьироваться от -84 до 127. Например, масштаб 2
вызывает округление до ближайшей сотой (3.456 округляется до
3.46). Масштаб может быть отрицательным, что вызывает
округление слева от десятичной точки. Например, масштаб -3
вызывает округление до ближайшей тысячи (3456 округляется до
3000). Нулевой масштаб вызывает округление до ближайшего
целого. Если вы не специфицируете масштаб, он по умолчанию
считается равным 0.
Основы 2-11
Подтипы NUMBER
Подтипы NUMBER, приведенные ниже, имеют тот же диапазон
допустимых значений, что и их базовый тип. Например, FLOAT -
это просто другое имя для NUMBER.
* DEC
* DECIMAL
* DOUBLE PRECISION
* FLOAT
* INT
* INTEGER
* NUMERIC
* REAL
* SMALLINT
Вы можете использовать эти подтипы для совместимости с типами
данных ANSI/ISO, IBM SQL/DS и IBM DB2, или если предпочитаете
более описательный идентификатор, нежели NUMBER.
CHAR
----
Вы используете тип данных CHAR для хранения символьных данных
фиксированной длины. Внутреннее представление данных зависит от
набора символов базы данных, которым может быть, например,
7-битовый код ASCII или кодовая страница 500 кода EBCDIC.
Тип данных CHAR принимает необязательный параметр, который
позволяет вам специфицировать максимальную длину (вплоть до
32767 байт). Синтаксис имеет следующий вид:
CHAR[(максимальная_длина)]
Для спецификации максимальной длины нельзя использовать
константу или переменную; вы должны использовать целочисленный
литерал. Если вы не специфицируете максимальную длину, она по
умолчанию считается равной 1.
Не забывайте, что вы специфицируете максимальную длину
переменной CHAR(n) в байтах, а не в символах. Поэтому, если
переменная CHAR(n) хранит мультибайтовые символы, ее
максимальная длина меньше, чем n символов.
Хотя максимальная длина переменной CHAR(n) составляет 32767
байт, максимальная ширина столбца базы данных типа CHAR равна
255 байт. Поэтому вы не можете вставлять в столбец CHAR
значения длиннее 255 байт. Вы можете вставлять значения CHAR(n)
в столбец базы данных LONG, ибо максимальная ширина столбца LONG
составляет 2147483647 (2**31 - 1) байт, или два гигабайта.
Однако вы не можете выбирать значение длиннее 32767 байт из
столбца LONG в переменную CHAR(n).
2-12 Руководство пользователя и справочник по PL/SQL
Подтипы CHAR
Подтипы CHAR, приведенные ниже, имеют тот же диапазон допустимых
значений, что и их базовый тип. Например, STRING - это просто
другое имя для CHAR.
* CHARACTER
* STRING
Вы можете использовать эти подтипы для совместимости с типами
данных ANSI/ISO, IBM SQL/DS и IBM DB2, или если предпочитаете
более описательный идентификатор, нежели CHAR.
VARCHAR2
--------
Вы используете тип данных VARCHAR2 для хранения символьных
данных переменной длины. Внутреннее представление данных
зависит от набора символов базы данных.
Тип данных VARCHAR2 принимает обязательный параметр, который
позволяет вам специфицировать максимальную длину (вплоть до
32767 байт). Синтаксис имеет следующий вид:
VARCHAR2(максимальная_длина)
Для спецификации максимальной длины нельзя использовать
константу или переменную; вы должны использовать целочисленный
литерал.
Не забывайте, что вы специфицируете максимальную длину
переменной VARCHAR2(n) в байтах, а не в символах. Поэтому, если
переменная VARCHAR2(n) хранит мультибайтовые символы, ее
максимальная длина меньше, чем n символов.
Хотя максимальная длина переменной VARCHAR2(n) составляет 32767
байт, максимальная ширина столбца базы данных типа VARCHAR2
равна 2000 байт. Поэтому вы не можете вставлять в столбец
VARCHAR2 значения длиннее 2000 байт. Вы можете вставлять
значения VARCHAR2(n) в столбец базы данных LONG, ибо
максимальная ширина столбца LONG составляет 2147483647 (2**31 -
1) байт, или два гигабайта. Однако вы не можете выбирать
значение длиннее 32767 байт из столбца LONG в переменную
VARCHAR2(n).
Важные семантические различия между базовыми типами CHAR и
VARCHAR2 описаны в приложении C.
Подтип VARCHAR
Подтип VARCHAR типа данных VARCHAR2 имеет тот же диапазон
допустимых значений, что и его базовый тип. Вы можете
использовать этот подтип для совместимости с типами данных
ANSI/ISO, IBM SQL/DS и IBM DB2. Однако тип VARCHAR должен в
будущем измениться в соответствии с развивающимися стандартами
SQL. Поэтому хорошей идеей является использовать VARCHAR2 вместо
VARCHAR.
Основы 2-13
LONG
----
Вы используете тип данных LONG для хранения символьных строк
переменной длины. Тип данных LONG подобен типу данных VARCHAR2,
с тем отличием, что максимальная длина значения LONG составляет
32760 байт.
Вы можете вставлять любое значение LONG в столбец базы данных
LONG, ибо максимальная ширина столбца LONG составляет 2147483647
байт. Однако вы не можете выбирать значение длиннее 32760 байт
из столбца LONG в переменную LONG.
Столбцы LONG могут хранить текст, массивы символов, или даже
небольшие документы. Вы можете обращаться к столбцам LONG в
предложениях UPDATE, INSERT и большинстве предложений SELECT, но
НЕ в выражениях, вызовах функций или некоторых фразах SQL, таких
как WHERE, GROPU BY и CONNECT BY. Для дополнительной информации
обратитесь к документу ORACLE7 Server SQL Language Reference
Manual.
RAW
---
Вы используете тип данных RAW для хранения двоичных данных или
байтовых строк. Например, в переменной RAW можно было бы
хранить последовательность графических символов или оцифрованное
изображение. Данные RAW напоминают символьные данные, с той
разницей, что PL/SQL не интерпретирует данных RAW. Аналогично,
ORACLE не выполняет никаких преобразований кодового множества,
когда вы передаете данные RAW из одной системы в другую.
Тип данных RAW принимает обязательный параметр, который
позволяет вам специфицировать максимальную длину (вплоть до
32767 байт). Синтаксис имеет следующий вид:
RAW(максимальная_длина)
Для спецификации максимальной длины нельзя использовать
константу или переменную; вы должны использовать целочисленный
литерал.
Хотя максимальная длина переменной RAW составляет 32767 байт,
максимальная ширина столбца базы данных типа RAW равна 255 байт.
Поэтому вы не можете вставлять в столбец RAW значения длиннее
255 байт. Вы можете вставлять значения RAW в столбец базы
данных LONG RAW, ибо максимальная ширина столбца LONG RAW
составляет 2147483647 байт. Однако вы не можете выбирать
значение длиннее 32767 байт из столбца LONG RAW в переменную
RAW.
2-14 Руководство пользователя и справочник по PL/SQL
LONG RAW
--------
Вы используете тип данных LONG RAW для хранения двоичных данных
или байтовых строк. Тип данных LONG RAW подобен типу данных
LONG, с тем отличием, что данные LONG RAW не интерпретируются
PL/SQL. Максимальная длина значения LONG RAW составляет 32760
байт.
Вы можете вставлять любое значение LONG RAW в столбец базы
данных LONG RAW, ибо максимальная ширина столбца LONG RAW
составляет 2147483647 байт. Однако вы не можете выбирать
значение длиннее 32760 байт из столбца LONG RAW в переменную
LONG RAW.
BOOLEAN
-------
Вы используете тип данных BOOLEAN для хранения предопределенных
значений TRUE и FALSE, а также "не-значения" NULL. Вспомните,
что NULL обозначает отсутствие, неизвестность или неприменимость
значения.
Тип данных BOOLEAN не принимает параметров. Булевской
переменной может быть присвоено лишь одно из трех возможных
значений: TRUE, FALSE или NULL. Нельзя вставлять значения TRUE
и FALSE в столбец базы данных. Более того, вы не можете
выбирать или извлекать значения столбцов базы данных в
переменные типа BOOLEAN.
DATE
----
Вы используете тип данных DATE для хранения значений дат,
которые имеют фиксированную длину. Тип данных DATE не принимает
параметров. Действительные значения для переменных DATE лежат в
интервале от 1 января 14712 г. до н.э. до 31 декабря 314712 г.
н.э.
При хранении в столбце базы данных, значения типа DATE включают
время дня, исчисляемое в секундах после полуночи. Компонента
даты, если она отсутствует, принимает по умолчанию значение даты
на первый день текущего месяца; компонента времени, если она
отсутствует, принимает по умолчанию время на полночь текущей
(или умалчиваемой) даты.
Основы 2-15
ROWID
-----
Внутренне, каждая таблица в базе данных ORACLE имеет
псевдостолбец ROWID, в котором хранятся 6-байтовые двоичные
значения, называемые ИДЕНТИФИКАТОРАМИ СТРОК. Идентификатор
строки уникально идентифицирует строку в таблице и предоставляет
самый быстрый способ доступа к конкретной строке. Вы
используете тип данных ROWID для хранения идентификаторов строк
в читабельном формате.
ROWID - это подтип типа CHAR. Поэтому, после выбора или
извлечения идентификатора строки в переменную ROWID, вы можете
использовать функцию ROWIDTOCHAR, которая преобразует двоичное
значение в 18-байтовую символьную строку, возвращая ее в формате
BBBBBBBB.RRRR.FFFF
где BBBBBBBB - номер блока в файле базы данных (блоки нумеруются
с 0), RRRR - номер строки в блоке (строки нумеруются с 0), FFFF
- номер файла базы данных. Все эти числа шестнадцатеричные.
Например, идентификатор строки
0000000E.000A.0007
указывает на 11-ю строку 15-го блока в 7-м файле базы данных.
Как правило, переменные ROWID сравниваются с псевдостолбцом
ROWID в фразе WHERE предложения UPDATE или DELETE, чтобы
идентифицировать последнюю строку, извлеченную курсором. Пример
приведен в секции "Извлечения между commit'ами" раздела
"Перекрытие умалчиваемых блокировок" в конце главы 4.
MLSLABEL
--------
В Trusted ORACLE, вы используете тип данных MLSLABEL для
хранения двоичных, переменной длины, меток операционной системы.
Trusted ORACLE использует такие метки для управления доступом к
данным. Для более подробной информации обратитесь к документу
Trusted ORACLE7 Server Administrator's Guide.
Вы можете использовать тип данных MLSLABEL для определения
столбца базы данных. Для ссылки на такой столбец можно
использовать атрибуты %TYPE и %ROWTYPE. Однако в стандартном
ORACLE такие столбцы могут содержать лишь пустые значения.
В Trusted ORACLE вы можете вставлять в столбец типа MSLABEL
любую действительную метку операционной системы. Если эта метка
имеет текстовый формат, Trusted ORACLE автоматически преобразует
ее в двоичное значение. Текстовая метка может иметь длину до
255 байт. Однако внутренняя длина значения MSLABEL имеет длину
от 2 до 5 байт.
В Trusted ORACLE вы также можете выбирать значения из столбца
MSLABEL в символьную переменную. Trusted ORACLE автоматически
преобразует внутреннее двоичное значение в значение типа
VARCHAR2.
2-16 Руководство пользователя и справочник по PL/SQL
----------------
Преобразования типов данных
Иногда бывает необходимо преобразовать значение из одного типа
данных в другой. Например, если вы хотите исследовать
идентификатор строки, вы должны преобразовать его в символьную
строку. PL/SQL поддерживает как явные, так и неявные
(автоматические) преобразования типов данных.
Явные преобразования типов
--------------------------
Чтобы специфицировать явные преобразования типов, вы используете
встроенные функции, которые преобразуют значения из одних типов
данных в другие. Рис.2-2 показывает, какую функцию следует
использовать в каждой возможной ситуации. Например, чтобы
преобразовать значение CHAR в значение NUMBER, вы используете
функцию TO_NUMBER.
Рис.2-2
Функции преобразования типов данных
Куда
г===========T=======T=========T========T===========¬
¦CHAR ¦DATE ¦NUMBER ¦RAW ¦ROWID ¦
г======+===========+=======+=========+========+===========¦
Откуда ¦CHAR ¦ ¦TO_DATE¦TO_NUMBER¦HEXTORAW¦CHARTORAWID¦
¦------+-----------+-------+---------+--------+-----------¦
¦DATE ¦TO_CHAR ¦ ¦ ¦ ¦ ¦
¦------+-----------+-------+---------+--------+-----------¦
¦NUMBER¦TO_CHAR ¦TO_DATE¦ ¦ ¦ ¦
¦------+-----------+-------+---------+--------+-----------¦
¦RAW ¦RAWTOHEX ¦ ¦ ¦ ¦ ¦
¦------+-----------+-------+---------+--------+-----------¦
¦ROWID ¦ROWIDTOCHAR¦ ¦ ¦ ¦ ¦
L======¦===========¦=======¦=========¦========¦===========-
Для дополнительной информации об этих функциях обратитесь к
секции "Функции преобразования типов данных" ниже в этой главе.
Основы 2-17
Неявные преобразования типов
----------------------------
Когда это имеет смысл, PL/SQL преобразует тип данных значения
неявно. Это позволяет вам использовать литералы, переменные и
параметры одного типа там, где ожидается другой тип. В
следующем примере, символьные переменные start_time и
finish_time хранят строковые значения, представляющие число
секунд после полуночи. Разность между этими значениями должна
быть присвоена числовой переменной elapsed_time. Поэтому PL/SQL
неявно преобразует значения CHAR в тип NUMBER.
DECLARE
start_time CHAR(5);
finish_time CHAR(5);
elapsed_time NUMBER(5);
BEGIN
/* Получить системное время в секундах после полуночи. */
SELECT TO_CHAR(SYSDATE, 'SSSSS')
INTO start_time FROM sys.dual;
-----------------------------------
-- выполнить какие-нибудь действия
-----------------------------------
/* Снова получить системное время. */
SELECT TO_CHAR(SYSDATE, 'SSSSS')
INTO finish_time FROM sys.dual;
/* Вычислить затраченное время в секундах. */
elapsed_time := finish_time - start_time;
INSERT INTO results VALUES (..., elapsed_time);
END;
Перед присваиванием выбранного значения столбца переменной
PL/SQL, если необходимо, преобразует это значение из типа данных
исходного столбца в тип данных целевой переменной. Это
происходит, например, когда вы выбираете значение столбца DATE в
переменную VARCHAR2. Аналогично, перед присваиванием или
сравнением значения переменной со значением столбца базы данных
PL/SQL, если необходимо, преобразует значение из типа данных
переменной в тип данных целевого столбца.
2-18 Руководство пользователя и справочник по PL/SQL
Если PL/SQL не может определить, какое неявное преобразование
необходимо, вы получите ошибку компиляции. В таких случаях вы
должны использовать явные функции преобразования типов данных.
На рис.2-3 показано, какие неявные преобразования типов данных
может выполнять PL/SQL.
Рис.2-3
Неявные преобразования типов данных
Куда
г=======T====T====T====T======T====T=====T========¬
¦BINARY_¦CHAR¦DATE¦LONG¦NUMBER¦RAW ¦ROWID¦VARCHAR2¦
¦INTEGER¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦
г========+=======+====+====+====+======+====+=====+========¦
Откуда ¦BINARY_ ¦ ¦ Да ¦ ¦ Да ¦ Да ¦ ¦ ¦ Да ¦
¦INTEGER ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦CHAR ¦ Да ¦ ¦ Да ¦ Да ¦ Да ¦ Да ¦ Да ¦ Да ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦DATE ¦ ¦ Да ¦ ¦ Да ¦ ¦ ¦ ¦ Да ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦LONG ¦ ¦ Да ¦ ¦ ¦ ¦ Да ¦ ¦ Да ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦NUMBER ¦ Да ¦ Да ¦ ¦ Да ¦ ¦ ¦ ¦ Да ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦RAW ¦ ¦ Да ¦ ¦ Да ¦ ¦ ¦ ¦ Да ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦ROWID ¦ ¦ Да ¦ ¦ ¦ ¦ ¦ ¦ Да ¦
¦--------+-------+----+----+----+------+----+-----+--------¦
¦VARCHAR2¦ Да ¦ Да ¦ Да ¦ Да ¦ Да ¦ Да ¦ Да ¦ ¦
L========¦=======¦====¦====¦====¦======¦====¦=====¦========-
Вы сами должны гарантировать преобразуемость значений.
Например, PL/SQL может преобразовать значение типа CHAR
'02-JUN-92' в значение типа DATE, но он не может преобразовать в
тип DATE символьную строку 'YESTERDAY'. Аналогично, PL/SQL не
может преобразовать в тип NUMBER значение CHAR, содержащее
нецифровые символы.
Основы 2-19
Сопоставление неявных и явных преобразований
--------------------------------------------
В общем случае, не следует полагаться на неявные преобразования
типов данных, потому что они могут повредить производительности
и подвержены изменениям от одной версии программного обеспечения
к другой. К тому же, неявные преобразования чувствительны к
контексту, и потому не всегда предсказуемы. Вместо этого
используйте функции преобразования типов данных. Это сделает
ваши приложения более надежными и сопровождаемыми.
Значения DATE
-------------
Когда вы выбираете значение столбца DATE в переменную CHAR или
VARCHAR2, PL/SQL должен преобразовать внутреннее двоичное
значение в символьное. Поэтому PL/SQL вызывает функцию TO_CHAR,
которая возвращает символьную строку в умалчиваемом формате
даты. Чтобы получить дату в другом формате, например, с
временем, или юлианскую дату, вы должны использовать функцию
TO_CHAR с подходящей маской формата.
Преобразование также необходимо, когда вы вставляете значение
типа CHAR или VARCHAR2 в столбец DATE. В этом случае PL/SQL
вызывает функцию TO_DATE, которая ожидает встретить умалчиваемый
формат даты. Чтобы вставить дату в ином формате, вы должны
вызывать TO_DATE с маской формата.
Значения RAW и LONG RAW
-----------------------
Когда вы выбираете значение столбца RAW или LONG RAW в
переменную CHAR или VARCHAR2, PL/SQL должен преобразовать
внутреннее двоичное значение в символьное. В этом случае PL/SQL
возвращает каждый двоичный байт значения RAW или LONG RAW как
пару символов, каждый из которых представляет шестнадцатеричный
эквивалент полубайта. Например, PL/SQL возвращает двоичный байт
11111111 как пару символов 'FF'. Функция RAWTOHEX выполняет
аналогичное преобразование.
Преобразование также необходимо, когда вы вставляете значение
типа CHAR или VARCHAR2 в столбец RAW или LONG RAW. Каждая пара
символов в значении переменной должна представлять
шестнадцатеричный эквивалент двоичного байта. Если какой-либо
из символов не представляет собой шестнадцатеричную цифру, будет
возбуждено исключение.
2-20 Руководство пользователя и справочник по PL/SQL
----------------
Объявления
Ваша программа хранит значения в переменных и константах. Во
время выполнения программы значения переменных могут изменяться,
а значения констант не могут.
Вы можете объявлять переменные и константы в декларативной части
любого блока PL/SQL, подпрограммы или пакета. Объявление
распределяет место для значения, специфицирует его тип данных и
задает имя, по которому можно обращаться к этому значению.
Объявление может также присвоить начальное значение и
специфицировать ограничение NOT NULL. Примеры:
birthdate DATE;
emp_count SMALLINT := 0;
acct_id VARCHAR2(5) NOT NULL := 'AP001';
Первое объявление именует переменную типа DATE. Второе
объявление именует переменную типа SMALLINT и использует
оператор присваивания (:=), чтобы присвоить этой переменной
нулевое начальное значение. Третье объявление именует
переменную типа VARCHAR2, специфицирует для нее ограничение NOT
NULL и присваивает ей начальное значение 'AP001'.
Нельзя присваивать значения NULL переменным или константам,
объявленным как NOT NULL. Если вы попытаетесь это сделать,
будет возбуждено предопределенное исключение VALUE_ERROR. За
ограничением NOT NULL должна следовать фраза инициализации; в
противном случае вы получите ошибку компиляции. Например,
следующее объявление незаконно:
acct_id VARCHAR2(5) NOT NULL; -- нет начального значения
Как показывают следующие примеры, инициализирующее выражение
может быть сколь угодно сложным и может ссылаться на ранее
инициализированные переменные и константы:
pi CONSTANT REAL := 3.14159;
radius REAL := 1;
area REAL := pi * radius**2;
В объявлениях констант зарезервированное слово CONSTANT должно
предшествовать спецификатору типа, как показывает следующий
пример:
credit_limit CONSTANT REAL := 5000.00;
Это объявление именует константу типа REAL и присваивает ей
начальное (и пожизненное) значение 5000. Константа ДОЛЖНА быть
инициализирована в своем объявлении; иначе вы получите ошибку
компиляции.
Основы 2-21
Использование DEFAULT
---------------------
Если хотите, вы можете использовать зарезервированное слово
DEFAULT вместо оператора присваивания, чтобы инициализировать
переменную или константу. Например, объявления
tax_year SMALLINT := 92;
valid BOOLEAN := FALSE;
можно переписать следующим образом:
tax_year SMALLINT DEFAULT 92;
valid BOOLEAN DEFAULT FALSE;
Можно также использовать DEFAULT для инициализации параметров
подпрограмм, параметров курсоров и полей в пользовательских
записях.
Использование %TYPE
-------------------
Атрибут %TYPE представляет тип данных переменной, константы или
столбца базы данных. В следующем примере, %TYPE представляет
тип данных переменной:
credit REAL(7,2);
debit credit%TYPE;
Переменные и константы, объявленные с атрибутом %TYPE,
трактуются так, как если бы они были объявлены с явным типом
данных. Например, в примере выше PL/SQL рассматривает
переменную debit как переменную типа REAL(7,2).
Следующий пример показывает, что объявление через %TYPE может
включать фразу инициализации:
balance NUMBER(7,2);
minimum_balance balance%TYPE := 10.00;
Атрибут %TYPE особенно полезен при объявлении переменных,
которые ссылаются на столбцы базы данных. Вы можете ссылаться
на таблицу и столбец, или указывать также и владельца таблицы,
как показывает следующий пример:
my_dname scott.dept.dname%TYPE;
Использование атрибута %TYPE при объявлении my_dname имеет два
преимущества. Во-первых, вы не обязаны знать точный тип столбца
dname. Во-вторых, если определение столбца dname изменится, то
тип данных переменной my_dname изменится соответственно во время
выполнения.
2-22 Руководство пользователя и справочник по PL/SQL
Заметим, однако, что ограничение столбца NOT NULL НЕ применяется
к переменным, объявленным через атрибут %TYPE. В следующем
примере, даже если столбец базы данных empno определен как NOT
NULL, вы все же можете присваивать пустое значение переменной
my_empno:
DECLARE
my_empno emp.empno%TYPE;
...
BEGIN
my_empno := NULL; -- это будет работать
...
END;
Использование %ROWTYPE
----------------------
Атрибут %ROWTYPE возвращает тип записи, представляющей строку в
таблице (или обзоре). Такая запись может содержать целую строку
данных, выбранных из таблицы или извлеченных курсором. В
следующем примере вы объявляете две записи. Первая из них
хранит строку, выбранную из таблицы emp. Вторая запись хранит
строку, извлеченную курсором c1.
DECLARE
emp_rec emp%ROWTYPE;
CURSOR c1 IS SELECT deptno, dname, loc FROM dept;
dept_rec c1%ROWTYPE;
...
Столбцы в строке таблицы и соответствующие поля в записи имеют
одинаковые имена и типы данных. В следующем примере вы
выбираете значения столбцов в запись с именем emp_rec:
DECLARE
emp_rec emp%ROWTYPE;
...
BEGIN
SELECT * INTO emp_rec FROM emp WHERE ...
...
END;
Значения столбцов, возвращаемые предложением SELECT, размещаются
в индивидуальных полях записи. Вы обращаетесь к конкретному
полю, используя квалифицированые ссылки. Например, вы могли бы
обратиться к полю deptno следующим образом:
IF emp_rec.deptno = 20 THEN ...
Кроме того, вы можете присваивать значение выражения PL/SQL
конкретному полю, как показывают следующие примеры:
emp_rec.ename := 'JOHNSON';
emp_rec.sal := emp_rec.sal * 1.15;
Основы 2-23
Нельзя включать выражений инициализации в объявления тех
переменных, которые используют %ROWTYPE. Тем не менее, есть два
способа присвоить значения сразу всем полям записи. Во-первых,
PL/SQL разрешает агрегатные присваивания между целыми записями,
если их объявления ссылаются на одну и ту же таблицу или курсор.
Например, следующие присваивания законны:
DECLARE
dept_rec1 dept%ROWTYPE;
dept_rec2 dept%ROWTYPE;
CURSOR c1 IS SELECT deptno, dname, loc FROM dept;
dept_rec3 c1%ROWTYPE;
dept_rec4 c1%ROWTYPE;
BEGIN
...
dept_rec1 := dept_rec2;
dept_rec4 := dept_rec3;
...
Однако, так как запись dept_rec2 базируется на таблице, а запись
dept_rec3 - на курсоре, следующее присваивание НЕЗАКОННО:
dept_rec2 := dept_rec3; -- незаконно
Во-вторых, вы можете присвоить записи список значений столбцов,
используя предложения SELECT...INTO или FETCH...INTO, как
показывает следующий пример. Имена столбцов должны появляться в
том порядке, в каком они были объявлены в предложениях CREATE
TABLE или CREATE VIEW при создании таблицы или обзора.
DECLARE
dept_rec dept%ROWTYPE;
...
BEGIN
SELECT deptno, dname, loc INTO dept_rec FROM dept
WHERE deptno = 30;
...
END;
Однако вы не можете использовать оператор присваивания для
присваивания записи списка значений. Поэтому следующее
присваивание НЕЗАКОННО:
имя_записи := (значение1, значение2, значение3); -- незаконно
Хотя вы можете извлекать целые записи, вы не можете вставлять
их. Например, следующее предложение незаконно:
INSERT INTO dept VALUES (dept_rec1); -- незаконно
2-24 Руководство пользователя и справочник по PL/SQL
Алиасы
Каждый элемент списка, извлекаемого из курсора, ассоциированного
с атрибутом %ROWTYPE, должен именоваться простым
идентификатором, или, если это выражения, должны иметь алиасы.
В следующем примере вы используете алиас wages:
-- доступен на диске в файле EXAMP4
DECLARE
CURSOR my_cursor IS SELECT sal + NVL(comm, 0) wages, ename
FROM emp;
my_rec my_cursor%ROWTYPE;
BEGIN
OPEN my_cursor;
LOOP
FETCH my_cursor INTO my_rec;
EXIT WHEN my_cursor%NOTFOUND;
IF my_cursor.wages > 2000 THEN
INSERT INTO temp VALUES (null, my_rec.wages,
my_rec.ename);
END IF;
END LOOP;
CLOSE my_cursor;
END;
Для дополнительной информации об алиасах имен столбцов
обратитесь к документу ORACLE7 Server SQL Language Manual.
Ограничения
-----------
PL/SQL не допускает ссылок вперед. Вы должны объявить
переменную или константу ПРЕЖДЕ, чем ссылаться на нее в других
предложениях, включая другие объявления. Например, следующее
объявление переменной maxi незаконно:
maxi INTEGER := 2 * mini;
mini INTEGER := 15;
Однако PL/SQL допускает упреждающие объявления подпрограмм. Для
дополнительной информации обратитесь к разделу "Упреждающие
объявления" в главе 6.
Некоторые языки позволяют вам объявлять целый список переменных,
принадлежащих одному и тому же типу данных. PL/SQL НЕ ПОЗВОЛЯЕТ
этого. Например, следующее объявление незаконно:
i, j, k SMALLINT; -- незаконно
Правильный вариант таков:
i SMALLINT;
j SMALLINT;
k SMALLINT;
Основы 2-25
----------------
Соглашения об именах
Одни и те же соглашения об именах действительны для всех
программных объектов и единиц PL/SQL, включая константы,
переменные, курсоры, исключения, процедуры, функции и пакеты.
Имена могут быть простыми, квалифицированными, удаленными или
квалифицированными удаленными. Например, вы можете обращаться к
процедуре с именем raise_salary любым из следующих способов:
raise_salary(...); -- простое
emp_actions.raise_salary(...); -- квалифицированное
raise_salary@newyork(...); -- удаленное
emp_actions.raise_salary@newyork(...); -- квалифиц. удаленное
В первом случае вы просто указываете имя процедуры. Во втором
случае вы должны квалифицировать имя процедуры именем пакета,
потому что процедура хранится в пакете с именем emp_actions. В
третьем случае вы обращаетесь к связи баз данных newyork, потому
что (независимая) процедура находится на удаленной базе данных.
В четвертом случае вы квалифицируете имя процедуры именем пакета
и указываете связь к базе данных.
Синонимы
--------
Вы можете создавать синонимы, чтобы обеспечить прозрачность
местоположения для объектов удаленных баз данных, таких как
таблицы, последовательности, обзоры, независимые подпрограммы и
пакеты. Однако нельзя создавать синонимы для объектов,
объявленных внутри подпрограмм или пакетов. К таким объектам
относятся константы, переменные, курсоры, исключения и
пакетированные процедуры. Для дополнительной информации
обратитесь к разделам "Удаленный доступ" в главе 4 и "Хранимые
подпрограммы" в главе 6.
Сфера
-----
Внутри одной сферы все объявляемые идентификаторы должны быть
уникальными. Так, переменные и параметры, даже если их типы
данных различаются, не могут иметь одинаковые имена. Например,
два из следующих трех объявлений незаконны:
DECLARE
valid_id BOOLEAN;
valid_id VARCHAR2(5); -- незаконное повторение имени
valid_id INTEGER; -- незаконное повторение имени
О правилах сферы, действующих для переменных и параметров,
смотрите в разделе "Сфера и видимость".
2-26 Руководство пользователя и справочник по PL/SQL
Чувствительность к регистру букв
--------------------------------
Как и прочие идентификаторы, имена переменных и параметров
нечевствительны к регистру букв. Например, PL/SQL рассматривает
следующие идентификаторы как одинаковые:
zip_code INTEGER;
Zip_code INTEGER;
ZIP_CODE INTEGER;
Имена таблиц базы данных
------------------------
В тех предложениях SQL, которые потенциально двусмысленны, имена
локальных переменных и формальных параметров имеют преимущество
над именами таблиц базы данных. Например, следующее предложение
UPDATE оказывается ошибочным из-за того, что PL/SQL полагает,
что emp ссылается на счетчик цикла:
FOR emp IN 1..5 LOOP
...
UPDATE emp SET bonus = 500 WHERE ...
END LOOP;
Аналогично, следующее предложение SELECT оказывается ошибочным
из-за того, что PL/SQL полагает, что emp ссылается на формальный
параметр:
PROCEDURE calc_bonus (emp NUMBER, bonus OUT REAL) IS
avg_sal REAL;
...
BEGIN
SELECT AVG(sal) INTO avg_sal FROM emp WHERE ...
...
END;
В таких случаях вы можете уточнять имя таблицы именем владельца,
как в следующем примере:
PROCEDURE calc_bonus (emp NUMBER, bonus OUT REAL) IS
avg_sal REAL;
...
BEGIN
SELECT AVG(sal) INTO avg_sal FROM scott.emp WHERE ...
...
END;
Однако лучшей практикой программирования было бы переименовать
такую переменную или формальный параметр.
Основы 2-27
Имена столбцов базы данных
--------------------------
Имена столбцов базы данных имеют преимущество над именами
локальных переменных и формальных параметров. Например,
следующее предложение DELETE удаляет из таблицы emp всех
сотрудников, а не только KING'а, потому что ORACLE полагает, что
оба слова ename в фразе WHERE ссылаются на столбец базы данных:
DECLARE
ename CHAR(10) := 'KING';
BEGIN
DELETE FROM emp WHERE ename = ename;
...
END;
В таких случаях, чтобы избежать двусмысленности, назначайте
локальным переменным и формальным параметрам имена с префиксом
my_, как в следующем примере:
DECLARE
my_ename CHAR(10);
...
Альтернативно, вы можете использовать метку блока, чтобы
квалифицировать локальные ссылки, например:
<>
DECLARE
ename CHAR(10) := 'KING';
BEGIN
DELETE FROM emp WHERE ename = main.ename;
...
END;
Следующий пример показывает, что вы можете использовать имя
подпрограммы для уточнения ссылок на локальные переменные и
формальные параметры:
PROCEDURE calc_bonus (empno NUMBER, bonus OUT REAL) IS
avg_sal REAL;
name CHAR(10);
job CHAR(15) := 'SALESMAN';
BEGIN
SELECT AVG(sal) INTO avg_sal FROM emp
WHERE job = calc_bonus.job; -- ссылка на локальную пер.
SELECT ename INTO name FROM emp
WHERE empno = calc_bonus.empno; -- ссылка на параметр
...
END;
2-28 Руководство пользователя и справочник по PL/SQL
----------------
Сфера и видимость
Ссылки на идентификатор разрешаются согласно его сфере и
видимости. СФЕРА идентификатора - это та область программной
единицы (блока, подпрограммы или пакета), из которой вы можете
ссылаться на этот идентификатор. Идентификатор называется
ВИДИМЫМ в тех областях, из которых вы можете ссылаться на него,
используя неквалицифированное имя.
Например, идентификаторы, объявленные в блоке PL/SQL, считаются
локальными в этом блоке и глобальными для всех его подблоков.
Если глобальный идентификатор переобъявляется в подблоке, то оба
идентификатора остаются в сфере. В подблоке, однако, будет
видимым лишь локальный идентификатор, потому что для ссылок к
глобальному идентификатору вам приходится использовать
квалифицированное имя.
На рис.2-4 показаны сфера и видимость переменной с именем x,
которая объявляется в окружающем блоке, а затем переобъявляется
в подблоке.
Рис.2-4
Сфера и видимость
Сфера : Видимость
----- : ---------
:
DECLARE : DECLARE
---------------¬ :
x REAL; ¦ : x REAL;
¦ : ---------------¬
BEGIN ¦ : BEGIN ¦
... ¦ : ... ¦
Внешняя x DECLARE ¦ : DECLARE ¦
--------- ¦ : ----------------
x REAL; ¦ : x REAL;
BEGIN ¦ : BEGIN
... ¦ : ...
END; ¦ : END;
¦ : ---------------¬
... ¦ : ... ¦
END; ¦ : END; ¦
---------------- : ----------------
:
.......................................:........................
:
DECLARE : DECLARE
x REAL; : x REAL;
BEGIN : BEGIN
... : ...
Внутренняя x DECLARE : DECLARE
------------ ------------¬ :
x REAL; ¦ : x REAL;
¦ : ------------¬
BEGIN ¦ : BEGIN ¦
... ¦ : ... ¦
END; ¦ : END; ¦
-------------- : -------------
... : ...
END; : END;
Основы 2-29
Хотя нельзя объявить идентификатор дважды в одном и том же
блоке, можно объявить одинаковые идентификаторы в двух разных
блоках. Объекты, представленные этими идентификаторами,
различны, и любое изменение одного из этих объектов не
затрагивает другой.
Однако из блока нельзя обращаться к идентификаторам, объявленным
в других блоках, вложенных на том же уровне, потому что такие
идентификаторы не являются ни локальными, ни глобальными по
отношению к этому блоку. Следующий пример иллюстрирует правила
сферы.
DECLARE
A CHAR;
B CHAR;
BEGIN
-- здесь доступны идентификаторы: A (CHAR), B
DECLARE
A INTEGER;
C REAL;
BEGIN
-- здесь доступны идентификаторы: A (INTEGER), B, C
END;
DECLARE
D REAL;
BEGIN
-- здесь доступны идентификаторы: A (CHAR), B, D
END;
-- здесь доступны идентификаторы: A (CHAR), B
END;
Вспомним, что глобальные идентификаторы можно переобъявлять в
подблоке, причем в этом случае локальное объявление имеет
преимущество, и подблок может ссылаться на глобальный
идентификатор лишь с помощью квалифицированного имени.
Квалификатором может служить метка окружающего блока, как
показывает следующий пример:
<>
DECLARE
birthdate DATE;
BEGIN
...
DECLARE
birthdate DATE;
BEGIN
...
IF birthdate = outer.birthdate THEN
...
END IF;
END;
END outer;
2-30 Руководство пользователя и справочник по PL/SQL
Или, как показывает следующий пример, квалификатором может быть
имя окружающей подпрограммы:
PROCEDURE check_credit (...) IS
rating NUMBER;
...
FUNCTION valid (...) RETURN BOOLEAN IS
rating NUMBER;
BEGIN
...
IF check_credit.rating < 3 THEN
...
END valid;
BEGIN
...
END check_credit;
----------------
Присваивания
Переменные и константы инициализируются при каждом входе в блок
или подпрограмму. По умолчанию переменные инициализируются
значением NULL. Поэтому, если вы явно не инициализируете
переменную, ее значение не определено, как показывает следующий
пример:
DECLARE
count INTEGER;
...
BEGIN
count := count + 1; -- count будет иметь значение null
...
Поэтому никогда не ссылайтесь на переменную, пока не присвоите
ей значение.
Для присваивания значений переменным можно использовать
предложения присваивания. Например, следующее предложение
присваивает переменной bonus новое значение, перекрывая ее
старое значение:
bonus := salary * 0.15;
Выражение, стоящее справа от оператора присваивания, может быть
сколь угодно сложным, но его результат должен иметь такой же тип
данных, что и тип переменной, или быть преобразуемым в этот тип.
Основы 2-31
Булевские значения
------------------
Булевской переменной можно присвоить лишь значения TRUE и FALSE,
либо "не-значение" NULL. Например, при объявлении
DECLARE
done BOOLEAN;
...
следующие предложения законны:
BEGIN
done := FALSE;
WHILE NOT done LOOP
...
END LOOP;
END;
Операторы отношений, будучи применены к выражениям PL/SQL,
возвращают булевские значения. Поэтому следующее присваивание
законно:
done := (count > 500);
Значения базы данных
--------------------
Альтернативно, вы можете использовать предложения SELECT и
FETCH, чтобы заставить ORACLE присвоить значение переменной.
Пример:
SELECT ename, sal + comm INTO last_name, wages FROM emp
WHERE empno = emp_id;
Для каждого элемента в списке SELECT должна быть специфицирована
соответствующая переменная в списке INTO. Кроме того, каждый
элемент списка SELECT должен возвращать значение, имеющее такой
же тип данных, что и тип соответствующей переменной, или
преобразуемый в этот тип. Для дополнительной информации о
предложениях SELECT и FETCH обратитесь к главе 9.
2-32 Руководство пользователя и справочник по PL/SQL
----------------
Выражения и сравнения
Выражения конструируются из операндов и операторов. ОПЕРАНД -
это переменная, константа, литерал или вызов функции,
поставляющий значение выражению. Пример простого
арифметического выражения:
-x / 2
Унарные операторы, такие как оператор отрицания (-), действуют
на один операнд; бинарные операторы, такие как оператор деления
(/), действуют на два операнда. В PL/SQL нет тернарных
операторов.
Простейшее выражение состоит из единственной переменной, которая
непосредственно поставляет свое значение. PL/SQL ВЫЧИСЛЯЕТ
выражение (т.е. находит его текущее значение), комбинируя
значения операндов так, как это предписано операторами. В
результате всегда получается единственное значение определенного
типа данных. PL/SQL определяет этот тип данных, изучая
выражение и контекст, в котором оно появляется.
Старшинство операторов
----------------------
Операции внутри выражения выполняются в определенном порядке, в
зависимости от их старшинства (приоритета). На рис.2-5 показан
умалчиваемый порядок операций от первой к последней (сверху
вниз).
Рис.2-5
Порядок операций
-----------------------------T---------------------------------¬
¦ Оператор ¦ Операция ¦
+----------------------------+---------------------------------+
¦ **, NOT ¦ возведение в степень, ¦
¦ ¦ логическое отрицание ¦
+----------------------------+---------------------------------+
¦ +, - ¦ тождественность, отрицание ¦
+----------------------------+---------------------------------+
¦ *, / ¦ умножение, деление ¦
+----------------------------+---------------------------------+
¦ +, -, || ¦ сложение, вычитание, ¦
¦ ¦ конкатенация ¦
+----------------------------+---------------------------------+
¦ =, !=, <, >, <=, >=, ¦ сравнение ¦
¦ IS NULL, LIKE, BETWEEN, IN ¦ ¦
+----------------------------+---------------------------------+
¦ AND ¦ конъюнкция ¦
+----------------------------+---------------------------------+
¦ OR ¦ включение ¦
L----------------------------+----------------------------------
Основы 2-33
Операторы с более высоким приоритетом выполняются первыми.
Например, оба следующих выражения дают результат 8, потому что
деление имеет более высокий приоритет, чем сложение:
5 + 12 / 4
12 / 4 + 5
Для операторов одного и того же приоритета не существует
никакого специального порядка выполнения.
Вы можете использовать скобки, чтобы управлять порядком
вычисления выражения. Например, следующее выражение дает 7, а
не 11, потому что скобки перекрывают умалчиваемый порядок:
(8 + 6) / 2
В следующем примере вычитание выполняется раньше деления, потому
что наиболее глубоко вложенное подвыражение всегда вычисляется
первым:
100 + (20 / 5 + (7 - 3))
Как показывает следующий пример, вы всегда можете использовать
скобки для улучшения читабельности, даже если в них нет
необходимости:
(salary * 0.05) + (commission * 0.25)
2-34 Руководство пользователя и справочник по PL/SQL
Логические операторы
--------------------
Логические операторы AND, OR и NOT вычисляются согласно логике
трех состояний, иллюстрируемой таблицами истинности на рис.2-6.
AND и OR - бинарные операторы; NOT - унарный оператор.
Рис.2-6
Таблицы истинности
г---------T---------T---------¬
NOT ¦ TRUE ¦ FALSE ¦ NULL ¦
-=========+=========+=========+=========¦
¦ ¦ FALSE ¦ TRUE ¦ NULL ¦
L---------¦---------+---------+----------
г---------T---------T---------¬
AND ¦ TRUE ¦ FALSE ¦ NULL ¦
-=========+=========+=========+=========¦
¦ TRUE ¦ TRUE ¦ FALSE ¦ NULL ¦
+---------+---------+---------+---------+
¦ FALSE ¦ FALSE ¦ FALSE ¦ FALSE ¦
+---------+---------+---------+---------+
¦ NULL ¦ NULL ¦ FALSE ¦ NULL ¦
L---------¦---------+---------+----------
г---------T---------T---------¬
OR ¦ TRUE ¦ FALSE ¦ NULL ¦
-=========+=========+=========+=========¦
¦ TRUE ¦ TRUE ¦ TRUE ¦ TRUE ¦
+---------+---------+---------+---------+
¦ FALSE ¦ TRUE ¦ FALSE ¦ NULL ¦
+---------+---------+---------+---------+
¦ NULL ¦ TRUE ¦ NULL ¦ NULL ¦
L---------¦---------+---------+----------
Как показывают таблицы истинности, AND возвращает значение TRUE,
только если оба операнда истинны. С другой стороны, OR
возвращает значение TRUE, когда любой из операндов истинен. NOT
возвращает противоположное значение (логическое отрицание)
своего операнда. Например, NOT TRUE возвращает FALSE.
NOT NULL возвращает NULL, потому что пустые значения не
определены. Отсюда следует, что, когда вы применяете оператор
NOT к NULL, результат также не определен. Будьте осторожны.
Пустые значения могут приводить к неожиданным результатам; см.
раздел "Обработка пустых значений" ниже в этой главе.
Если вы не используете скобок для специфицирования порядка
вычислений, то этот порядок определяется старшинством
операторов. Сравните следующие выражения:
NOT valid AND done NOT (valid AND done)
Если булевские переменные valid и done обе имеют значение FALSE,
то первое выражение возвратит FALSE, потому что NOT старше, чем
AND; иными словами, первое выражение эквивалентно следующему:
(NOT valid) AND done
Однако второе выражение возвратит TRUE.
Основы 2-35
Операторы сравнения
-------------------
Операторы сравнения сравнивают одно выражение с другим.
Результатом сравнения всегда является булевское значение TRUE,
FALSE или NULL. Обычно вы используете операторы сравнения в
фразе WHERE предложений манипулирования данными SQL, а также в
предложениях условного управления.
Операторы отношений
Операторы отношений позволяют вам сравнивать сколь угодно
сложные выражения. Следующая таблица показывает смысл каждого
оператора:
Оператор Смысл
--------------------------------
= равно
!= не равно
< меньше чем
> больше чем
<= меньше или равно
>= больше или равно
Оператор IS NULL
Оператор IS NULL возвращает булевское значение TRUE, если его
операнд есть NULL, и FALSE в противном случае. Сравнения, в
которых участвуют пустые значения (NULL), всегда дают NULL.
Поэтому для проверки значения на пустоту не используйте
выражений вида
IF значение = NULL THEN ...
Вместо этого используйте предложение:
IF значение IS NULL THEN ...
Будьте внимательны. Пустые значения могут приводить к
неожиданным результатам. Смотрите раздел "Обработка пустых
значений" ниже в этой главе.
Оператор LIKE
Оператор LIKE служит для сравнения символьного значения с
образцом. Прописные и строчные буквы различаются. LIKE
возвращает булевское значение TRUE, если символьные образцы
совпадают, и FALSE в противном случае.
Образцы, сравниваемые оператором LIKE, могут включать два
специальных ("поисковых") символа. Подчеркивание (_) совпадает
с любым одиночным символом; процент (%) совпадает с нулем или
более любых символов. Например, если значение переменной ename
равно 'JOHNSON', то следующее выражение дает TRUE:
ename LIKE 'J%SON'
2-36 Руководство пользователя и справочник по PL/SQL
Оператор BETWEEN
Оператор BETWEEN проверяет, лежит ли значение в указанном
интервале. Он означает "больше или равно меньшему значению и
меньше или равно большему значению". Например, следующее
выражение дает FALSE:
45 BETWEEN 38 AND 44
Оператор IN
Оператор IN проверяет на членство в множестве. Он означает
"равно любому члену множества". Множество может включать пустые
значения, но они игнорируются. Например, следующее выражение НЕ
удалит строк, в которых столбец ename пуст:
DELETE FROM emp WHERE ename IN (NULL, 'KING', 'FORD');
Более того, выражения вида
значение NOT IN множество
дают FALSE, если множество содержит NULL. Например, следующее
предложение не удалит никаких строк:
DELETE FROM emp WHERE ename NOT IN (NULL, 'KING');
Оператор конкатенации
Оператор конкатенации (||) присоединяет одну строку символов к
другой. Например, выражение
'suit' || 'case'
возвратит результат
'suitcase'
Если оба операнда имеют тип CHAR, то оператор конкатенации
возвращает значение типа CHAR. В противном случае возвращается
значение типа VARCHAR2.
Основы 2-37
Булевские выражения
-------------------
PL/SQL позволяет вам сравнивать переменные и константы как в
предложениях SQL, так и в процедурных выражениях. Такие
сравнения, называемые БУЛЕВСКИМИ ВЫРАЖЕНИЯМИ, состоят из простых
или сложных выражений, разделенных операторами отношений. Часто
сами булевские выражения соединяются логическими операторами
AND, OR или NOT. Булевское выражение всегда дает TRUE, FALSE или
NULL.
В предложении SQL булевские выражения позволяют специфицировать
строки в таблице, на которые воздействует предложение. В
процедурном предложении булевские выражения являются основой для
условного управления. Есть три вида булевских выражений:
арифметические, символьные и календарные.
Арифметические
Вы можете использовать операторы отношений для сравнения чисел
на равенство или неравенство. Такие сравнения - количественные;
это значит, что одно число больше другого, если оно представляет
большее количество. Например, при присваиваниях
number1 := 75;
number2 := 70;
следующее выражение дает TRUE:
number1 > number2
Символьные
Вы можете также сравнивать символьные значения на равенство или
неравенство. Такие сравнения опираются на сопоставляющую
последовательность, используемую набором символов базы данных.
(СОПОСТАВЛЯЮЩАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ - это внутренняя
упорядоченность символов в наборе символов базы данных,
основанная на числовых кодах, сопоставляемых каждому символу).
Одно символьное значение больше второго, если оно следует за
вторым в сопоставляющей последовательности. Например, при
присваиваниях
string1 := 'Kathy';
string2 := 'Kathleen';
следующее выражение дает TRUE:
string1 > string2
Однако при сравнении символьных значений существуют
семантические различия между типами данных CHAR и VARCHAR2. Для
дополнительной информации обратитесь к приложению C.
2-38 Руководство пользователя и справочник по PL/SQL
Календарные
Вы можете сравнивать значения дат. Такие сравнения -
хронологические: одна дата больше другой, если она более
поздняя. Например, при присваиваниях
date1 := '01-JAN-91';
date2 := '31-DEC-90';
следующее выражение дает TRUE:
date1 > date2
Рекомендации
Как правило, не следует сравнивать вещественные числа на
равенство или неравенство. Вещественные числа хранятся как
приближенные значения. Так, например, следующее условие не
должно дать TRUE:
count := 1;
IF count = 1.0 THEN ...
Старайтесь использовать скобки при сравнениях. Например,
следующее выражение незаконно, потому что выражение 100 < tax
дает булевское значение TRUE или FALSE, которое нельзя
сравнивать с числом 500:
100 < tax < 500 -- незаконно
Правильная запись такова:
(100 < tax) AND (tax < 500)
Булевская переменная сама по себе имеет значение TRUE или FALSE.
Поэтому ее сравнение с булевским значением TRUE или FALSE
избыточно. Например, если переменная done имеет тип BOOLEAN, то
предложение вида
IF done = TRUE THEN ...
можно записать проще:
IF done THEN ...
Основы 2-39
Обработка пустых значений
-------------------------
Чтобы избежать некоторых общих ошибок, держите в голове
следующие правила:
* сравнения, в которых участвует NULL, всегда дают NULL
* применение NOT к значению NULL дает NULL
* в предложениях условного управления, если условие дает
NULL, соответствующая группа предложений не выполняется
В следующем примере, вы могли бы ожидать, что ряд предложений
будет выполнен, потому что x и y не равны. Однако вспомните,
что пустые значения не определены. Поэтому равны ли x и y,
считается неизвестным; условие IF дает NULL, и ряд предложений
обходится.
x := 5;
y := NULL;
IF x != y THEN -- это условие даст NULL, а не TRUE
ряд_предложений; -- не выполняется
END IF;
В следующем примере, вы могли бы ожидать, что ряд предложений
будет выполнен, потому что a и b выглядят равными. Однако,
опять-таки, это считается неизвестным; условие IF дает NULL, и
ряд предложений обходится.
a := NULL;
b := NULL;
IF a = b THEN -- это условие даст NULL, а не TRUE
ряд_предложений; -- не выполняется
END IF;
Оператор NOT
Вспомните, что применение логического оператора NOT к значению
NULL дает NULL. Таким образом, следующие два предложения не
всегда эквивалентны:
IF x > y THEN | IF NOT x > y THEN
high := x; | high := y;
ELSE | ELSE
high := y; | high := x;
END IF; | END IF;
Ряд предложений в фразе ELSE выполняется тогда, когда условие IF
дает FALSE или NULL. Поэтому, когда хотя бы одно из значений x
или y есть NULL, первое предложение IF присвоит переменной high
значение y, тогда как второе - значение x. Если оба значения x
и y непусты, то оба предложения IF работают одинаково.
2-40 Руководство пользователя и справочник по PL/SQL
Строки нулевой длины
PL/SQL трактует любую строку нулевой длины как NULL. Это
включает значения, возвращаемые символьными функциями и
булевскими выражениями. Например, следующие предложения
присваивают целевым переменным пустые значения:
null_string := TO_VARCHAR2('');
zip_code := SUBSTR(address, 25, 0);
valid := (name != '');
Поэтому для проверки пустых строк используйте оператор IS NULL,
как показано ниже:
IF my_string IS NULL THEN ...
Оператор конкатенации
Оператор конкатенации игнорирует пустые операнды. Например,
выражение
'apple' || NULL || NULL || 'sauce'
даст значение 'applesauce'.
Функции
Если функции передается пустой аргумент, она возвращает NULL, за
исключением следующих трех случаев.
DECODE
Функция DECODE сравнивает свой первый аргумент с одним или
несколькими поисковыми выражениями, которые спарены с
результирующими выражениями. Любое из поисковых и
результирующих выражений может быть пустым. Если сравнение
успешно, возвращается соответствующий результат. В следующем
примере, если значение rating пусто, DECODE возвращает значение
1000:
credit_limit := DECODE(rating, NULL, 1000, 'B', 2000, 'A',4000);
NVL
Если ее первый аргумент есть NULL, функция NVL возвращает
значение своего второго аргумента. В следующем примере, если
hire_date есть NULL, NVL возвратит значение SYSDATE; в противном
случае NVL возвратит значение hire_date:
start_date := NVL(hire_date, SYSDATE);
REPLACE
Если ее второй аргумент есть NULL, функция REPLACE возвращает
значение своего первого аргумента, независимо от того,
присутствует ли необязательный третий аргумент. Например, после
присваивания
new_string := REPLACE(old_string, NULL, my_string);
значения old_string и new_string будут одинаковыми.
Основы 2-41
Если ее третий аргумент есть NULL, функция REPLACE возвращает
значение своего первого аргумента, из которого удалены все
вхождения второго аргумента. Например, после присваиваний
syllabified_name := 'Gold-i-locks';
name := REPLACE(syllabified_name, '-', NULL)
значением переменной name будет
'Goldilocks'
Если и второй, и третий аргументы пусты, функция REPLACE просто
возвращает свой первый аргумент.
----------------
Встроенные функции
PL/SQL предоставляет много мощных функций, помогающих вам
манипулировать данными. Вы можете использовать функции всюду,
где допускаются выражения того же типа. Более того, вы можете
вкладывать вызовы функций друг в друга.
Встроенные функции распадаются на следующие категории:
* функции сообщений об ошибках
* числовые функции
* символьные функции
* функции преобразований
* календарные функции
* смешанные функции
В предложениях SQL можно использовать все встроенные функции, за
исключением функций сообщений об ошибках SQLCODE и SQLERRM. В
процедурных предложениях можно использовать все встроенные
функции, за исключением смешанной функции DECODE.
Групповые функции SQL AVG, MIN, MAX, COUNT, SUM, STDDEV и
VARIANCE не встроены в PL/SQL. Тем не менее, вы можете
использовать их в предложениях SQL (но не в процедурных
предложениях PL/SQL). Для дополнительной информации о групповых
функциях обратитесь к разделу "Поддержка SQL" в главе 4.
Для каждой встроенной функции приводятся ее аргументы, типы
данных этих аргументов, и тип данных возвращаемого значения.
Следующий пример показывает, что функция LENGTH принимает
аргумент типа VARCHAR2 и возвращает значение типа NUMBER:
function LENGTH (str VARCHAR2) return NUMBER
2-42 Руководство пользователя и справочник по PL/SQL
Функции сообщений об ошибках
----------------------------
Две функции, SQLCODE и SQLERRM, дают вам информацию об ошибках
выполнения PL/SQL. Эти функции НЕ допускаются в предложениях
SQL.
SQLCODE
function SQLCODE return NUMBER
Возвращает номер последнего возбужденного исключения. Эта
функция имеет смысл только в обработчике исключений. Вне
обработчика она всегда возвращает 0.
Для внутренне определенных исключений SQLCODE возвращает номер
ошибки ORACLE, которая передала управление обработчику. Этот
номер будет отрицательным, исключая случай ошибки ORACLE "no
data found"; в этом случае SQLCODE возвращает +100. Для
пользовательских исключений, SQLCODE возвращает +1, если вы не
использовали прагму EXCEPTION_INIT, чтобы ассоциировать ваше
исключение с номером ошибки ORACLE; в этом случае SQLCODE
возвращает этот номер ошибки. (Для дополнительной информации о
прагме EXCEPTION_INIT обратитесь к соответствующему разделу в
главе 5.)
SQLERRM
function SQLERRM [(error_number NUMBER)] return CHAR
Возвращает сообщение об ошибке, ассоциированной с текущим
значением SQLCODE.
Функция SQLERRM без аргумента имеет смысл только в обработчике
исключений. Вне обработчика, SQLERRM без аргумента всегда
возвращает сообщение "ORA-0000: normal, successful completion".
Для внутренне определенных исключений SQLERRM возвращает
сообщение, ассоциированное с встретившейся ошибкой ORACLE. Это
сообщение начинается с кода ошибки ORACLE.
Для пользовательских исключений, SQLERRM возвращает сообщение
"User-Defined Exception", если вы не использовали прагму
EXCEPTION_INIT, чтобы ассоциировать ваше исключение с номером
ошибки ORACLE; в этом случае SQLERRM возвращает соответствующее
сообщение об ошибке.
Вы можете передать номер ошибки error_number как аргумент
функции SQLERRM; в этом случае SQLERRM возвращает сообщение,
ассоциированное с этим номером ошибки.
Основы 2-43
Числовые функции
----------------
Числовые функции принимают числовые аргументы и возвращают
числовые значения. Трансцендентные функции включают
тригонометрические, логарифмические и экспоненциальные функции.
Обычные тригонометрические функции (SIN, COS и TAN) и
гиперболические тригонометрические функции (SINH, COSH и TANH)
тесно связаны. Если n - вещественное число, а i - (мнимый)
квадратный корень из -1, то
SIN(i*n) = i*SINH(n)
COS(i*n) = COSH(n)
TAN(i*n) = i*TANH(n)
ABS
function ABS (n NUMBER) return NUMBER
Возвращает абсолютное значение n.
CEIL
function CEIL (n NUMBER) return NUMBER
Возвращает наименьшее целое, большее или равное n.
COS
function COS (a NUMBER) return NUMBER
Возвращает косинус угла a, выраженного в радианах. Радиан равен
57.29578 градусов (180/pi). Если ваш угол a выражен в градусах,
возьмите просто COS(a/57.29578).
COSH
function COSH (n NUMBER) return NUMBER
Возвращает гиперболический косинус числа n.
EXP
function EXP (n NUMBER) return NUMBER
Возвращает число e, возведенное в степень n. Число e
(приблизительно 2.71728) выражает основание натуральных
логарифмов.
FLOOR
function FLOOR (n NUMBER) return NUMBER
Возвращает наибольшее целое, меньшее или равное n.
LN
function LN (n NUMBER) return NUMBER
Возвращает натуральный логарифм числа n, где n больше 0.
LOG
function LOG (m NUMBER, n NUMBER) return NUMBER
Возвращает логарифм по основанию m числа n, где m больше 1, а n
больше 0.
2-44 Руководство пользователя и справочник по PL/SQL
MOD
function MOD (m NUMBER, n NUMBER) return NUMBER
Возвращает остаток от деления m на n. Если n равно 0,
возвращается m.
POWER
function POWER (m NUMBER, n NUMBER) return NUMBER
Возвращает m в степени n. База m и степень n могут быть любыми
числами, но если m отрицательно, то n должно быть целым.
ROUND
function ROUND (m NUMBER [, n NUMBER]) return NUMBER
Округляет m до n десятичных позиций. Если n опущено, то m
округляется до нуля десятичных позиций (т.е. до целого). Число
n может быть отрицательным, что позволяет округлять до десятков,
сотен и т.п.
SIGN
function SIGN (n NUMBER) return NUMBER;
Возвращает -1, если n меньше нуля, 0, если n равно 0, и 1, если
n больше нуля.
SIN
function SIN (a NUMBER) return NUMBER
Возвращает синус угла a, выраженного в радианах.
SINH
function SINH (n NUMBER) return NUMBER
Возвращает гиперболический синус числа n.
SQRT
function SQRT (n NUMBER) return NUMBER
Возвращает квадратный корень числа n, которое не может быть
отрицательным.
TAN
function TAN (a NUMBER) return NUMBER
Возвращает тангенс угла a, выраженного в радианах.
TANH
function TANH (n NUMBER) return NUMBER
Возвращает гиперболический тангенс числа n.
TRUNC
function TRUNC (m NUMBER [, n NUMBER]) return NUMBER
Возвращает m, усеченное до n десятичных позиций. Если n
опущено, то m усекается до нуля десятичных позиций (т.е. до
целого). Число n может быть отрицательным, что позволяет
обнулять цифры десятков, сотен и т.п.
Основы 2-45
Символьные функции
------------------
Символьные функции принимают символьные аргументы. Некоторые
символьные функции возвращают символьные значения, остальные
возвращают числовые значения. Функции, возвращающие символьные
значения, всегда возвращают значение типа VARCHAR2, с двумя
исключениями. Функции UPPER и LOWER возвращают значение типа
CHAR, если им передан аргумент типа CHAR, и значение типа
VARCHAR2 в противном случае.
ASCII
function ASCII (char VARCHAR2) return NUMBER
Возвращает код сопоставляющей последовательности, который
представляет символ char в наборе символов базы данных. Функция
ASCII является обратной к функции CHR.
CHR
function CHR (num NUMBER) return VARCHAR2
Возвращает символ, который имеет код n в сопоставляющей
последоватнльности набора символов базы данных. Функция CHR
является обратной к функции ASCII.
CONCAT
function CONCAT (str1 VARCHAR2, str2 VARCHAR2) return VARCHAR2
Присоединяет строку str2 к строке str1 и возвращает результат.
Если один из аргументов пуст, CONCAT возвращает другой аргумент.
Если оба аргумента пусты, CONCAT возвращает NULL.
INITCAP
function INITCAP (str VARCHAR2) return VARCHAR2
Возвращает строку str, в которой первая буква каждого слова
преобразована в прописную, а остальные в строчные. Слова
отделяются друг от друга пропусками или не алфавитно-цифровыми
символами.
INSTR
function INSTR (str1 VARCHAR2, str2 VARCHAR2 [, pos NUMBER
[, n NUMBER]]) return VARCHAR2
Возвращает позицию n-го вхождения строки str2 в строку str1,
начиная поиск с позиции pos. Если значение pos отрицательно,
INSTR осуществляет поиск от конца строки str1. Если не задано
pos, подразумевается 1. Если не задано n, подразумевается 1.
Позиция позвращается относительно первого символа строки str1,
даже если поиск начинается не с позиции 1, и выражена в
СИМВОЛАХ. Если поиск неудачен, возвращается 0.
2-46 Руководство пользователя и справочник по PL/SQL
INSTRB
function INSTRB (str1 VARCHAR2, str2 VARCHAR2 [, pos NUMBER
[, n NUMBER]]) return VARCHAR2
Возвращает позицию n-го вхождения строки str2 в строку str1,
начиная поиск с позиции pos. Если значение pos отрицательно,
INSTR осуществляет поиск от конца строки str1. Если не задано
pos, подразумевается 1. Если не задано n, подразумевается 1.
Позиция позвращается относительно первого символа строки str1,
даже если поиск начинается не с позиции 1, и выражена в БАЙТАХ.
Если поиск неудачен, возвращается 0. Для однобайтовых наборов
символов функция INSTRB эквивалентна функции INSTR.
LENGTH
function LENGTH (str CHAR) return NUMBER
function LENGTH (str VARCHAR2) return NUMBER
Возвращает число СИМВОЛОВ в строке str. Если строка str имеет
тип CHAR, то в длину входят хвостовые пробелы. Если строка str
пуста, LENGTH возвращает NULL.
LENGTHB
function LENGTHB (str CHAR) return NUMBER
function LENGTHB (str VARCHAR2) return NUMBER
Возвращает число БАЙТ в строке str. Если строка str имеет тип
CHAR, то в длину входят хвостовые пробелы. Если строка str
пуста, LENGTHB возвращает NULL. Для однобайтовых наборов
символов функция LENGTHB эквивалентна функции LENGTH.
LOWER
function LOWER (str CAR) return CHAR
function LOWER (str VARCHAR2) return VARCHAR2
Возвращает строку str, в которой все буквы преобразованы в
строчные.
LPAD
function LPAD (str VARCHAR2, len NUMBER [, pad VARCHAR2])
return VARCHAR2
Возвращает строку str, дополненную слева до длины len цепочкой
символов pad, повторяющейся столько раз, сколько необходимо.
Если строка pad не указана, подразумевается пробел. Если строка
str длиннее len символов, то LPAD возвращает первые len символов
строки str.
LTRIM
function LTRIM (str VARCHAR2, [, set VARCHAR2]) return VARCHAR2
Возвращает строку str, из которой удалены начальные символы
вплоть до первого символа, не принадлежащего множеству set.
Если множество set не задано, подразумевается пробел.
Основы 2-47
NLS_INITCAP
function NLS_INITCAP (str VARCHAR2 [,nlsparms VARCHAR2])
return VARCHAR2
Возвращает строку str, в которой первая буква каждого слова
преобразована в прописную, а остальные в строчные. Слова
отделяются друг от друга пропусками или не алфавитно-цифровыми
символами. Значение nlsparms должно иметь форму
'NLS_SORT = '
где sort - либо название лингвистической сортировки, либо
ключевое слово BINARY. Лингвистическая сортировка удовлетворяет
специальным требованиям языка при преобразованиях букв. Это
может привести к тому, что NLS_INITCAP возвратит строку другой
длины, чем входная строка str. Если аргумент nlsparms опущен,
NLS_INITCAP использует умалчиваемую сортировку для текущей
сессии. Для дополнительной информации обратитесь к документу
ORACLE7 Server Application Developer's Guide.
NLS_LOWER
function NLS_LOWER (str VARCHAR2 [,nlsparms VARCHAR2])
return VARCHAR2
Возвращает строку str, в которой все буквы преобразованы в
строчные. Значение nlsparms должно иметь форму
'NLS_SORT = '
где sort - либо название лингвистической сортировки, либо
ключевое слово BINARY. Лингвистическая сортировка удовлетворяет
специальным требованиям языка при преобразованиях букв. Это
может привести к тому, что NLS_LOWER возвратит строку другой
длины, чем входная строка str. Если аргумент nlsparms опущен,
NLS_LOWER использует умалчиваемую сортировку для текущей сессии.
Для дополнительной информации обратитесь к документу ORACLE7
Server Application Developer's Guide.
NLS_UPPER
function NLS_UPPER (str VARCHAR2 [,nlsparms VARCHAR2])
return VARCHAR2
Возвращает строку str, в которой все буквы преобразованы в
прописные. Значение nlsparms должно иметь форму
'NLS_SORT = '
где sort - либо название лингвистической сортировки, либо
ключевое слово BINARY. Лингвистическая сортировка удовлетворяет
специальным требованиям языка при преобразованиях букв. Это
может привести к тому, что NLS_UPPER возвратит строку другой
длины, чем входная строка str. Если аргумент nlsparms опущен,
NLS_UPPER использует умалчиваемую сортировку для текущей сессии.
Для дополнительной информации обратитесь к документу ORACLE7
Server Application Developer's Guide.
2-48 Руководство пользователя и справочник по PL/SQL
NLSSORT
function NLSSORT (str VARCHAR2 [,nlsparms VARCHAR2]) return RAW
Возвращает значение строки str в лингвистической
последовательности сортировки, специфицированной аргументом
nlsparms. Если аргумент nlsparms опущен, NLSSORT использует
умалчиваемую сортировку для текущей сессии. Значение nlsparms
должно иметь форму
'NLS_SORT = '
где sort - либо название лингвистической сортировки, либо
ключевое слово BINARY. Если специфицировано BINARY, то NLSSORT
возвращает строку str.
В фразе WHERE, функция NLSSORT позволяет специфицировать
сравнения на базе лингвистического, а не двоичного,
упорядочения. NLSSORT также позволяет вам управлять поведением
фразы ORDER BY независимо от параметра NLS_SORT. Для
дополнительной информации обратитесь к документу ORACLE7 Server
Application Developer's Guide.
REPLACE
function REPLACE (str1 VARCHAR2, str2 VARCHAR2
[,str3 VARCHAR2]) return VARCHAR2
Возвращает строку str1, в которой каждое вхождение подстроки
str2 заменено строкой str3. Если строка str3 не задана, то все
вхождения подстроки str2 удаляются из строки str1. Если не
специфицированы ни поисковая подстрока, ни строка замены, то
REPLACE возвращает NULL.
RPAD
function RPAD (str VARCHAR2, len NUMBER [, pad VARCHAR2])
return VARCHAR2
Возвращает строку str, дополненную справа до длины len цепочкой
символов pad, повторяющейся столько раз, сколько необходимо.
Если строка pad не указана, подразумевается пробел. Если строка
str длиннее, чем len символов, то RPAD возвращает первые len
символов строки str.
RTRIM
function RTRIM (str VARCHAR2, [, set VARCHAR2]) return VARCHAR2
Возвращает символьную строку str, из которой удалены конечные
символы после последнего символа, не принадлежащего множеству
set. Если множество set не задано, подразумевается пробел.
SOUNDEX
function SOUNDEX (str VARCHAR2) return VARCHAR2
Возвращает строку, представляющую собой фонетический эквивалент
слов строки str. Фонетическое представление слов позволяет вам
сравнивать слова, которые пишутся по-разному, но произносятся
похоже. Это представление определено в книге Д.Кнута "Искусство
программирования", том 3.
Основы 2-49
SUBSTR
function SUBSTR (str VARCHAR2, pos NUMBER [, len NUMBER]])
return VARCHAR2
Возвращает подстроку строки str, начинающуюся с СИМВОЛЬНОЙ
позиции pos и содержащую len символов (или, если число len
опущено, все символы до конца строки str). Значение pos не
может быть нулевым. Если значение pos отрицательно, SUBSTR
подсчитывает символы от конца строки str. Число len должно быть
положительным.
SUBSTRB
function SUBSTRB (str VARCHAR2, pos NUMBER [, len NUMBER]])
return VARCHAR2
Возвращает подстроку строки str, начинающуюся с БАЙТОВОЙ позиции
pos и содержащую len символов (или, если число len опущено, все
символы до конца строки str). Значение pos не может быть
нулевым. Если значение pos отрицательно, SUBSTR подсчитывает
байты от конца строки str. Число len должно быть положительным.
Для однобайтовых наборов символов функция SUBSTRB эквивалентна
функции SUBSTR.
TRANSLATE
function TRANSLATE (str VARCHAR2, set1 VARCHAR2, set2 CHAR)
return VARCHAR2
Возвращает строку str, в которой все символы из множества set1
заменены соответствующими символами из множества set2, а все
прочие символы оставлены без изменений. Если set1 содержит
больше символов, чем set2, то лишние символы в конце множества
set1 не имеют аналогов в множестве set2. Поэтому, если такие
символы встречаются в строке str, TRANSLATE удаляет их из
результирующего значения.
UPPER
function UPPER (str CHAR) return CHAR
function UPPER (str VARCHAR2) return VARCHAR2
Возвращает строку str, в которой все буквы преобразованы в
прописные.
2-50 Руководство пользователя и справочник по PL/SQL
Функции преобразования
----------------------
Функции преобразования конвертируют значение из одного типа
данных в другой.
CHARTOROWID
function CHARTOROWID (str CHAR) return ROWID
function CHARTOROWID (str VARCHAR2) return ROWID
Преобразует строку str из типа CHAR или VARCHAR2 в тип ROWID.
CONVERT
function CONVERT (str VARCHAR2, set1 VARCHAR2 [, set2 VARCHAR2])
return VARCHAR2
Преобразует строку str из одного набора символов (set2) в другой
(set1). Как set1, так и set2 могут быть столбцами базы данных
или литералами, представляющими имя набора символов. Следующая
таблица показывает некоторые общеупотребительные наборы
символов:
Набор символов Описание
----------------------------------------------------------------
US7ASCII Американский 7-битовый ASCII
WE8DEC Западноевропейский 8-битовый DEC
WE8HP Западноевропейский 8-битовый HP Laserjet
F7DEC Французский 7-битовый DEC
WE8EBCDIC500 Западноевропейский IBM EBCDIC, кодовая
страница 500
WE8PC850 IBM PC, кодовая страница 850
WE8ISO8859P1 Западноевропейский 8-битовый ISO 8859-1
Для полного преобразования, целевой набор символов (set1) должен
содержать представления всех символов исходного набора символов
(set2). В противном случае используются символы замены, которые
вы можете специфицирорвать при определении набора символов.
HEXTORAW
function HEXTORAW (str CHAR) return RAW
function HEXTORAW (str VARCHAR2) return RAW
Преобразует шестнадцатеричную строку str из типа CHAR или
VARCHAR2 в тип RAW.
RAWTOHEX
function RAWTOHEX (bin RAW) return VARCHAR2
Преобразует двоичное значение bin из типа RAW в
шестнадцатеричную строку типа VARCHAR2.
Основы 2-51
RAWIDTOCHAR
function RAWIDTOCHAR (bin ROWID) return VARCHAR2
Преобразует двоичное значение bin из типа RAWID в
шестнадцатеричную строку типа VARCHAR2.
TO_CHAR для дат
function TO_CHAR (dte DATE [, fmt VARCHAR2 [, nlsparms] ])
return VARCHAR2
Преобразует дату dte в символьную строку типа VARCHAR2 в
формате, заданном моделью формата fmt. (Допустимые модели
формата приведены в описании функции TO_DATE.) Если вы опустите
fmt, подразумевается умалчиваемый формат даты.
Аргумент nlsparms специфицирует язык, в котором возвращаются
названия или сокращения месяцев и дней. Он имеет следующий вид:
'NLS_DATE_LANGUAGE = <язык>'
Если вы опустите nlsparms, то TO_CHAR использует умалчиваемый
язык для текущей сессии.
TO_CHAR для чисел
function TO_CHAR (num NUMBER [, fmt VARCHAR2 [, nlsparms] ])
return VARCHAR2
Преобразует число num в символьную строку типа VARCHAR2 в
формате, заданном моделью формата fmt. (Допустимые модели
формата приведены в описании функции TO_NUMBER.) Если вы
опустите fmt, число num преобразуется в строку символов такой
длины, которой достаточно для всех значащих цифр.
Аргумент nlsparms специфицирует следующие символы, которые
возвращаются элементами числового формата:
* десятичный разделитель (обозначенный ниже как d)
* групповой разделитель (обозначенный ниже как g)
* местный символ валюты
* международный символ валюты
Этот аргумент имеет следующую форму:
'NLS_NUMERIC_CHARACTERS = ''dg'',
NLS_CURRENCY = ''текст'',
NLS_ISO_CURRENCY = ''текст'' '
Заметьте, что внутри строки, заключенной в апострофы, каждый
апостроф представляется двумя апострофами подряд. Если вы
опустите nlsparms, то TO_CHAR использует умалчиваемые значения
соответствующих параметров для текущей сессии.
2-52 Руководство пользователя и справочник по PL/SQL
TO_CHAR для меток
function TO_CHAR (label MLSLABEL [, fmt VARCHAR2])
return VARCHAR2
Преобразует метку label типа MLSLABEL в символьную строку типа
VARCHAR2 в формате, заданном моделью формата fmt. Если вы
опустите fmt, подразумевается умалчиваемый формат меток.
Этот вариант функции TO_CHAR используется только в Trusted
ORACLE. Для дополнительной информации обратитесь к документу
Trusted ORACLE7 Server Administrator's Guide.
TO_DATE
function TO_DATE (str VARCHAR2 [, fmt VARCHAR2 [, nlsparms] ])
return DATE
function TO_DATE (num NUMBER, [, fmt VARCHAR2 [, nlsparms] ])
return DATE
Преобразует строку str или число num в значение даты в формате,
заданном fmt. Допустимые модели формата приведены в следующей
таблице:
Модель формата Описание
----------------------------------------------------------------
CC,SCC век (S префиксует даты до н.э. минусом)
YYYY,SYYYY год (S префиксует даты до н.э. минусом)
IYYY год в стандарте ISO
YYY,YY,Y последние три, две или одна цифра года
IYY,IY,I то же для года ISO
Y,YYY год с запятой
YEAR,SYEAR год прописью (S префиксует даты до н.э.
минусом)
RR последние две цифры года в новом веке
BC,AD индикатор BC или AD
B.C.,A.D. индикатор B.C. или A.D.
Q квартал (1-4)
MM месяц (1-12)
RM римский номер месяца (I-XII)
MONTH имя месяца
MON сокращенное имя месяца
WW неделя года (1-53)
IWW неделя года (1-52 или 1-53) по ISO
W неделя месяца (1-5)
DDD день года (1-366)
(продолжение на следующей странице)
Основы 2-53
Модель формата Описание
----------------------------------------------------------------
DD день месяца (1-31)
D день недели (1-7)
DAY имя дня
DY сокращенное имя дня
J юлианский день (число дней с 1 января
4712 г. до н.э.)
AM,PM индикатор полудня
A.M.,P.M. индикатор полудня с точками
HH,HH12 час дня (1-12)
HH24 час суток (0-23)
MI минута (0-59)
SS секунда (0-59)
SSSSS секунд после полуночи (0-86399)
Если формат опущен, подразумевается, что строка str задана в
умалчиваемом формате даты. Если аргумент fmt имеет значение 'J'
(юлианский день), то число num должно быть целым.
Аргумент nlsparms специфицирует язык, в котором возвращаются
названия или сокращения месяцев и дней. Он имеет следующий вид:
'NLS_DATE_LANGUAGE = <язык>'
Если вы опустите nlsparms, то TO_DATE использует умалчиваемый
язык для текущей сессии.
TO_LABEL
function TO_LABEL (str CHAR [, fmt VARCHAR2]) return MLSLABEL
function TO_LABEL (str VARCHAR2 [, fmt VARCHAR2])
return MLSLABEL
Преобразует строку str, которая содержит метку в формате,
специфицированном моделью формата fmt, в значение типа MLSLABEL.
Если вы опускаете fmt, то строка str должна быть в умалчиваемом
формате меток.
Эта функция используется только в Trusted ORACLE. Для
дополнительной информации обратитесь к документу Trusted ORACLE7
Server Administrator's Guide.
2-54 Руководство пользователя и справочник по PL/SQL
TO_MULTI_BYTE
function TO_MULTI_BYTE (str CHAR) return CHAR
function TO_MULTI_BYTE (str VARCHAR2) return VARCHAR2
Возвращает строку str, в которой все однобайтовые символы
преобразованы в свои мультибайтовые эквиваленты. Однобайтовые
символы, не имеющие мультибайтовых эквивалентов, остаются без
изменений. Эта функция полезна лишь в том случае, если набор
символов вашей базы данных содержит как однобайтовые, так и
мультибайтовые символы.
TO_NUMBER
function TO_NUMBER (str CHAR [, fmt VARCHAR2 [, nlsparms] ])
return NUMBER
function TO_NUMBER (str VARCHAR2 [, fmt VARCHAR2 [, nlsparms] ])
return NUMBER
Преобразует строку str из значения типа CHAR или VARCHAR2 в
значение типа NUMBER в формате, специфицированном моделью
формата fmt. Модель числового формата состоит из элементов
формата, приведенных на следующей таблице:
Элемент Пример Описание
----------------------------------------------------------------
9 9999 значащая цифра
0 0999 ведущий нуль (вместо пробела)
$ $999 ведущий знак доллара
B B999 ведущий пробел (вместо нуля)
MI 999MI хвостовой знак минус
S S999 ведущий знак (плюс или минус)
PR 999PR отрицательные значения в угловых скобках
D 99D99 десятичный символ
G 9G99 разделитель групп
C C999 символ валюты в стандарте ISO
L L999 местный символ валюты
, 9,999 запятая
. 9.999 точка
V 999V99 умножение на 10 в степени n, где n -
число девяток после V
EEEE 9.99EEEE научная нотация
RN,rn RN римское числительное в верхнем или
нижнем регистре
Основы 2-55
Строка str должна представлять действительное число. Аргумент
nlsparms специфицирует следующие символы, которые возвращаются
элементами числового формата:
* десятичный разделитель (обозначенный ниже как d)
* групповой разделитель (обозначенный ниже как g)
* местный символ валюты
* международный символ валюты
Этот аргумент имеет следующую форму:
'NLS_NUMERIC_CHARACTERS = ''dg'',
NLS_CURRENCY = ''текст'',
NLS_ISO_CURRENCY = ''текст'' '
Заметьте, что внутри строки, заключенной в апострофы, каждый
апостроф представляется двумя апострофами подряд. Если вы
опустите nlsparms, то TO_NUMBER использует умалчиваемые значения
соответствующих параметров для текущей сессии.
TO_SINGLE_BYTE
function TO_SINGLE_BYTE (str CHAR) return CHAR
function TO_SINGLE_BYTE (str VARCHAR2) return VARCHAR2
Возвращает строку str, в которой все мультибайтовые символы
преобразованы в свои однобайтовые эквиваленты. Мультибайтовые
символы, не имеющие однобайтовых эквивалентов, остаются без
изменений. Эта функция полезна лишь в том случае, если набор
символов вашей базы данных содержит как однобайтовые, так и
мультибайтовые символы.
Календарные функции
-------------------
Календарные функции принимают аргументы и возвращают значения в
формате DATE, за исключением функции MONTH_BETWEEN, которая
возвращает числовое значение.
ADD_MONTHS
function ADD_MONTHS (dte DATE, num NUMBER) return DATE
function ADD_MONTHS (num NUMBER, dte DATE) return DATE
Обе формы функции имеют один и тот же эффект. К дате dte
прибавляется num месяцев, и возвращается результирующая дата.
Число num должно быть целым. ADD_MONTHS всегда возвращает дату,
числовое значение порции дня которой совпадает с днем даты dte,
с одним исключением. Если день даты dte превышает число дней в
результирующем месяце, то дата, возвращаемая функцией
ADD_MONTHS, будет последним днем месяца. Таким путем ADD_MONTHS
компенсирует различающиеся числа дней в разных месяцах.
LAST_DAY
function LAST_DAY (dte DATE) return DATE
Возвращает дату последнего дня месяца, содержащего дату dte.
2-56 Руководство пользователя и справочник по PL/SQL
MONTHS_BETWEEN
function MONTHS_BETWEEN (dte1 DATE, dte2 DATE) return NUMBER
Возвращает число месяцев между датами dte1 и dte2. Если dte1
позже dte2, результат положителен. Если dte1 раньше dte2,
результат отрицателен. Если даты dte1 и dte2 попадают на
одинаковые (или последние) дни соответствующих месяцев, то
MONTHS_BETWEEN возвращает целое число. В противном случае
MONTHS_BETWEEN возвращает дробное число, которое базируется на
31-дневном месяце и учитывает разницу между компонентами времени
в датах dte1 и dte2.
NEW_TIME
function NEW_TIME (dte DATE, zon1 VARCHAR2, zon2 VARCHAR2)
return DATE
При данном значении даты/времени dte в часовом поясе zon1
возвращает соответствующее значение даты/времени в часовом поясе
zon2. Следующая таблица содержит допустимые значения символьных
выражений zon1 и zon2:
Значение Описание
---------------------------------------------------------
AST Атлантическое стандартное время
ADT Атлантическое дневное время
BST Берингово стандартное время
BDT Берингово дневное время
CST Центральное стандартное время
CDT Центральное дневное время
EST Восточное стандартное время
EDT Восточное дневное время
GMT Среднее время по Гринвичу
HST Аляска-Гавайи, стандартное время
HDT Аляска-Гавайи, дневное время
MST Маунтин, стандартное время
MDT Маунтин, дневное время
NST Ньюфаундленд, стандартное время
PST Тихоокеанское стандартное время
PDT Тихоокеанское дневное время
YST Юкон, стандартное время
YDT Юкон, дневное время
Основы 2-57
NEXT_DAY
function NEXT_DAY (dte DATE, day VARCHAR2) return DATE
Возвращает первую дату после даты dte, название дня недели
которой совпадает с значением day. day должно быть правильным
названием одного из семи дней недели.
ROUND
function ROUND (dte DATE [, fmt VARCHAR2]) return DATE
Возвращает дату dte, округленную согласно модели формата fmt.
Если формат опущен, подразумевается 'DD'. Следующая таблица
показывает допустимые модели форматов и соответствующие им
единицы округления:
Модель формата Единицы округления
---------------------------------------------------------
CC,SCC век
SYYY,YYY,YEAR,
SYEAR,YYY,YY,Y год (округляется вверх на 1 июля)
Q квартал (округляется вверх на
16-е число 2-го месяца квартала)
MONTH,MON,MM месяц (округляется вверх на 16-е)
WW начало недели ГОДА
W начало недели МЕСЯЦА
DDD,DD,J день
DAY,DY,D ближайшее воскресенье
HH,HH12,HH24 час
MI минута
SYSDATE
function SYSDATE return DATE
Возвращает текущее значение даты/времени в системе. Эта функция
не принимает аргументов.
TRUNC
function TRUNC (ted DATE [, fmt VARCHAR2]) return DATE
Возвращает значение даты dte, компонента времени которой усечена
согласно модели формата fmt. (Список допустимых моделей формата
приведен в описании функции ROUND.) Если формат опущен,
компонента времени удаляется из даты, т.е. осуществляется
усечение на ближайший день.
2-58 Руководство пользователя и справочник по PL/SQL
Смешанные функции
-----------------
DECODE
function DECODE (expr, search1, result1 [, search2, result2] ...
[default] )
Значение выражения expr сравнивается с каждым из значений
search. Если expr совпадает с каким-либо search, возвращается
соответствующее значение result. Если ни одного совпадения не
найдено, возвращается значение default (или NULL, если значение
default опущено).
expr может иметь любой тип данных, но значения search должны
иметь тот же тип, как у expr. Возвращаемое значение
принудительно приводится к тому типу данных, как у result1.
Функция DECODE допускается только в предложениях SQL.
DUMP
function DUMP (expr DATE [, fmt BINARY_INTEGER
[, pos BINARY_INTEGER [, len BINARY_INTEGER]]])
return VARCHAR2
function DUMP (expr NUMBER [, fmt BINARY_INTEGER
[, pos BINARY_INTEGER [, len BINARY_INTEGER]]])
return VARCHAR2
function DUMP (expr VARCHAR2 [, fmt BINARY_INTEGER
[, pos BINARY_INTEGER [, len BINARY_INTEGER]]])
return VARCHAR2
Возвращает внутреннее представление значения выражения expr.
Аргумент fmt определяет формат возвращаемого значения
(8=восьмеричный, 10=десятичный, 16=шестнадцатеричный,
17=символьный). Аргументы pos (позиция) и len (длина)
специфицируют, какая часть представления должна быть возвращена.
По умолчанию возвращается полное представление в десятичном
виде.
GREATEST
function GREATEST (expr1, expr2, expr3, ...)
Возвращает наибольшее значение из списка значений. Все значения
expr в списке, кроме первого, приводятся к типу данных первого
значения (expr1) перед выполнением сравнений. Поэтому типы
данных всех значений должны быть совместимы с типом данных
первого значения. Функция GREATEST сравнивает выражения,
используя недополняющую семантику (см. приложение C).
GREATEST_LB
function GREATEST_LB (label [,label] ...) return MLSLABEL
Возвращает наибольшую нижнюю границу из списка меток. Каждая
метка label в списке должна иметь тип данных MLSLABEL или должна
быть литералом в апострофах в умалчиваемом формате меток.
Эта функция используется только в Trusted ORACLE. Для
дополнительной информации обратитесь к документу Trusted ORACLE7
Server Administrator's Guide.
Основы 2-59
LEAST
LEAST (expr1, expr2, expr3, ...)
Возвращает наименьшее значение из списка значений. Все значения
expr в списке, кроме первого, приводятся к типу данных первого
значения (expr1) перед выполнением сравнений. Поэтому типы
данных всех значений должны быть совместимы с типом данных
первого значения. первого значения. Функция LEAST сравнивает
выражения, используя недополняющую семантику (см. приложение C).
LEAST_UB
function LEAST_UB (label [,label] ...) return MLSLABEL
Возвращает наименьшую верхнюю границу из списка меток. Каждая
метка label в списке должна иметь тип данных MLSLABEL или должна
быть литералом в апострофах в умалчиваемом формате меток.
Эта функция используется только в Trusted ORACLE. Для
дополнительной информации обратитесь к документу Trusted ORACLE7
Server Administrator's Guide.
NVL
function NVL (str1 CHAR, str2 CHAR) return CHAR
function NVL (dte1 DATE, dte2 DATE) return DATE
function NVL (bool1 BOOLEAN, bool2 BOOLEAN) return BOOLEAN
function NVL (num1 NUMBER, num2 NUMBER) return NUMBER
function NVL (str1 VARCHAR2, str2 VARCHAR2) return VARCHAR2
function NVL (lbl1 MLSLABEL, lbl2 MLSLABEL) return MLSLABEL
Все формы функции принимают два аргумента одинакового типа и
возвращают значение того же типа. Если первый аргумент не NULL,
возвращается значение первого аргумента. Если первый аргумент
есть NULL, возвращается значение второго аргумента.
UID
function UID return NUMBER
Возвращает идентификационный номер, который ORACLE назначил
текущему пользователю. Эта функция не имеет аргументов.
USER
function USER return VARCHAR2
Возвращает имя текущего пользователя ORACLE. Эта функция не
имеет аргументов.
2-60 Руководство пользователя и справочник по PL/SQL
USERENV
function USERENV (str VARCHAR2) return VARCHAR2
Возвращает информацию о текущей сессии, полезную для составления
аудиторской таблицы или для определения используемого языка и
набора символов.
Символьная строка str может иметь одно из следующих значений:
'ENTRYID' Возвращает идентификатор аудиторской записи.
'LABEL' Возвращает метку сессии. Эта опция доступна
только в Trusted ORACLE. Для дополнительной
информации обратитесь к документу Trusted
ORACLE7 Server Administrator's Guide.
'LANGUAGE' Возвращает используемые язык, территорию и набор
символов базы данных.
'SESSIONID' Возвращает идентификатор аудиторской сессии.
'TERMINAL' Возвращает идентификатор терминала в
операционной системе.
Нельзя специфицировать опцию 'ENTRYID' или 'SESSIONID' в
предложениях SQL, обращающихся к удаленной базе данных.
VSIZE
function VSIZE (expr DATE) return NUMBER
function VSIZE (expr NUMBER) return NUMBER
function VSIZE (expr VARCHAR2) return NUMBER
Возвращает число байт во внутреннем представлении выражения
expr. Если expr есть NULL, VSIZE возвращает NULL.
Основы 2-61
----------------
Таблицы PL/SQL
PL/SQL предоставляет два составных типа данных: TABLE и RECORD.
Этот раздел обсуждает тип данных TABLE; в следующем разделе
обсуждается тип данных RECORD.
Объекты типа TABLE называются ТАБЛИЦАМИ PL/SQL. Эти таблицы
моделируют таблицы базы данных (но не являются таковыми).
Таблицы PL/SQL используют первичный ключ, чтобы предоставить вам
доступ к строкам по аналогии с массивом.
Как и размер таблицы базы данных, размер таблицы PL/SQL НЕ
ОГРАНИЧИВАЕТСЯ. Иными словами, число строк в таблице PL/SQL
может возрастать динамически. Поэтому ваша таблица PL/SQL
растет по мере добавления в нее новых строк.
Таблица PL/SQL может иметь один столбец и один первичный ключ,
оба непоименованные. Столбец может принадлежать любому
скалярному типу, но первичный ключ должен принадлежать типу
BINARY_INTEGER. В будущих версиях PL/SQL таблицы PL/SQL смогут
иметь несколько поименованных столбцов и составные первичные
ключи любого типа.
Объявление таблиц PL/SQL
------------------------
Таблицы PL/SQL должны объявляться за два шага. Прежде всего вы
объявляете (поименованный) тип TABLE, а затем объявляете таблицы
PL/SQL этого типа. Вы можете объявлять типы TABLE в
декларативной части любого блока, подпрограммы или пакета,
используя следующий синтаксис:
TYPE имя_типа IS TABLE OF
{ тип_столбца | переменная%TYPE | таблица.столбец%TYPE }
[NOT NULL] INDEX BY BINARY_INTEGER;
где имя_типа - спецификатор типа, используемый в последующих
объявлениях таблиц PL/SQL, а тип_столбца - любой скалярный (не
составной) тип данных, такой как CHAR, DATE или NUMBER.
Альтернативно, для спецификации типа столбца можно использовать
атрибут %TYPE.
2-62 Руководство пользователя и справочник по PL/SQL
В следующем примере вы объявляете тип TABLE с именем
EnameTabTyp:
DECLARE
TYPE EnameTabTyp IS TABLE OF CHAR(10)
INDEX BY BINARY_INTEGER;
...
Вы можете использовать атрибут %TYPE для предоставления типа
столбца, как показывает следующий пример:
DECLARE
TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;
...
После определения типа EnameTabTyp вы можете объявлять таблицы
PL/SQL этого типа, например:
ename_tab EnameTabTyp;
Идентификатор ename_tab представляет всю таблицу PL/SQL.
Таблица PL/SQL не ограничена, потому что ее первичный ключ может
принимать любое значение в интервале допустимых значений для
BINARY_INTEGER. Как следствие, вы не можете инициализировать
таблицу PL/SQL в ее объявлении. Например, следующее объявление
незаконно:
ename_tab EnameTabTyp := ('CASEY','STUART','CHU'); --незаконно
Таблицы PL/SQL подчиняются обычным правилам сферы и инстанциации
(инстанциация - это создание нового экземпляра программного
объекта). В пакете, таблицы PL/SQL инстанциируются при первом
обращении к этому пакету, и перестают существовать, когда вы
выходите из приложения или заканчиваете сессию базы данных. В
блоке или подпрограмме, таблицы PL/SQL инстанциируются при входе
в блок или подпрограмму, и перестают существовать, когда вы
выходите из блока или подпрограммы.
Основы 2-63
Как и скалярные переменные, таблицы PL/SQL могут объявляться как
формальные параметры процедур и функций. Ограничения, которые
применяются к скалярным параметрам, применимы и к таблицам
PL/SQL. Приведем несколько пакетированных примеров:
PACKAGE emp_actions IS
TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;
TYPE SalTabTyp IS TABLE OF emp.sal%TYPE
INDEX BY BINARY_INTEGER;
ename_tab EnameTabTyp;
sal_tab SalTabTyp;
...
PROCEDURE hire_batch
(ename_tab EnameTabTyp,
sal_tab SalTabTyp,
...);
PROCEDURE log_names
(ename_tab EnameTabTyp,
num BINARY_INTEGER);
...
END emp_actions;
Чтобы определить поведение формальных параметров, вы используете
моды параметров, которые обсуждаются в главе 6. Параметры OUT
позволяют возвращать значения вызывающей программе при выходе из
подпрограммы. Если выход успешен, PL/SQL присваивает
фактическим параметрам значения строк. Однако, если вы выходите
с необработанным исключением, PL/SQL не присваивает фактическим
параметрам значения строк.
Обращение к таблицам PL/SQL
---------------------------
Чтобы обратиться к строке таблицы PL/SQL, вы специфицируете
значение первичного ключа, используя синтаксис, напоминающий
индексацию массива:
имя_таблицы_plsql(значение_первичного_ключа)
где значение_первичного_ключа есть значение типа BINARY_INTEGER.
Например, чтобы обратиться к третьей строке таблицы PL/SQL
ename_tab, вы пишете:
ename_tab(3) ...
Допустимый диапазон значений BINARY_INTEGER - от -2**31 - 1 до
2**31 - 1, так что значение первичного ключа может быть
отрицательным. Например, следующая ссылка законна:
ename_tab(-5) ...
По поводу исключения, обратитесь к разделу "Использование
хост-массивов с таблицами PL/SQL" в главе 8.
2-64 Руководство пользователя и справочник по PL/SQL
Чтобы присвоить конкретной строке таблицы PL/SQL значение
выражения PL/SQL, используйте следующий синтаксис:
имя_таблицы_plsql(значение_первичного_ключа) := выражение_plsql;
В следующем примере вы назначаете сумму переменных salary и
increase пятой строке таблицы PL/SQL sal_tab:
sal_tab(5) := salary + increase;
В следующем примере курсорный цикл FOR используется для загрузки
двух таблиц PL/SQL. Курсорный цикл FOR неявно объявляет свой
индекс цикла как запись, открывает курсор, ассоциированный с
данным запросом, последовательно извлекает строки значений из
курсора в поля записи, а затем закрывает курсор. Для более
подробной информации о курсорных циклах FOR обратитесь к разделу
"Управление курсорами" в главе 4.
DECLARE
TYPE EnameTabTyp IS TABLE OF emp.ename%TYPE
INDEX BY BINARY_INTEGER;
TYPE SalTabTyp IS TABLE OF emp.sal%TYPE
INDEX BY BINARY_INTEGER;
ename_tab EnameTabTyp;
sal_tab SalTabTyp;
i BINARY_INTEGER := 0;
...
BEGIN
-- загрузить имена и оклады сотрудников в таблицы PL/SQL
FOR emprec IN (SELECT ename, sal FROM emp) LOOP
i := i + 1;
ename_tab(i) := emprec.ename;
sal_tab(i) := emprec.sal;
END LOOP;
-- обработать таблицы
process_sals(ename_tab, sal_tab);
...
END;
Основы 2-65
В следующем примере используется квалифицированная ссылка для
обращения к пакету emp_actions, который вы видели выше в этом
разделе:
DECLARE
...
i BINARY_INTEGER := 0;
BEGIN
-- загрузить имена сотрудников в таблицу PL/SQL
FOR emprec IN (SELECT ename FROM emp ORDER BY ename) LOOP
i := i + 1;
emp_actions.ename_tab(i) := emprec.ename;
END LOOP;
-- обработать таблицу PL/SQL
emp_actions.log_name(emp_actions.ename_tab, i);
...
END;
Пока строке таблицы PL/SQL не присвоено значение, эта строка не
существует. При попытке обратиться к неинициализированной
строке PL/SQL возбуждает предопределенное исключение
NO_DATA_FOUND. Рассмотрим следующий пример:
DECLARE
TYPE JobTabTyp IS TABLE OF CHAR(14)
INDEX BY BINARY_INTEGER;
job_tab JobTabTyp;
BEGIN
job_tab(1) := 'CLERK';
IF job_tab(2) = 'CLERK' THEN -- возбуждает NO_DATA_FOUND
...
END IF;
...
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- сюда, потому что job_tab(2) не существует
...
END;
Ссылки на строки, подобные job_tab(1), допускаются как
фактические параметры в вызовах подпрограмм, но к ним применимы
те же ограничения, что и к скалярным переменным.
2-66 Руководство пользователя и справочник по PL/SQL
Поддержка счетчика строк
------------------------
Вспомним, что размер таблицы PL/SQL не ограничен. Поэтому, если
вы хотите поддерживать счетчик строк, вы должны для этой цели
объявить переменную. Например, вы могли бы объявить переменную
типа INTEGER с именем row_count, в которой будете хранить
текущее число строк в вашей таблице PL/SQL.
Что произойдет, если таблица PL/SQL станет слишком велика?
Рассмотрим следующий пример:
DECLARE
TYPE DateTabTyp IS TABLE OD DATE
INDEX BY BINARY_INTEGER;
hiredate_tab DateTabTyp;
i BINARY_INTEGER := 0;
BEGIN
/* Инициализировать таблицу PL/SQL. */
LOOP
i := i + 1;
hiredate_tab(i) := SYSDATE;
-- предложение EXIT WHEN опущено
END LOOP;
...
END;
В каждой итерации основного цикла к таблице PL/SQL добавляется
очередная строка. Цикл не может завершиться, потому что он не
содержит предложения EXIT WHEN. В конце концов, PL/SQL
переполнит имеющуюся память и возбудит предопределенное
исключение STORAGE_ERROR.
Основы 2-67
Вставка и извлечение строк
--------------------------
Вы должны использовать цикл, чтобы вставлять (INSERT) значения
из таблицы PL/SQL в столбец базы данных. Аналогично, вы должны
использовать цикл, чтобы извлекать (FETCH) значения из столбца
базы данных в таблицу PL/SQL. (Для таблиц PL/SQL не существует
потокового интерфейса, подобного тому, который прекомпиляторы
ORACLE предоставляют для хост-массивов.) Например, при
объявлениях
DECLARE
TYPE EmpnoTabTyp IS TABLE OF NUMBER(4)
INDEX BY BINARY_INTEGER;
TYPE EnameTabTyp IS TABLE OF CHAR(10)
INDEX BY BINARY_INTEGER;
...
empno_tab EmpnoTabTyp;
ename_tab EnameTabTyp;
...
вы могли бы использовать следующую процедуру, чтобы вставить
значения из таблиц PL/SQL в таблицу базы данных emp:
PROCEDURE insert_emp_data
(rows BINARY_INTEGER,
empno_tab EmpnoTabTyp,
ename_tab EnameTabTyp,
...) IS
BEGIN
FOR i IN 1..rows LOOP
INSERT INTO emp (empno, ename, ...)
VALUES (empno_tab(i), ename_tab(i), ...);
END LOOP;
END;
Аналогично, вы могли бы использовать следующую процедуру, чтобы
извлечь все строки из таблицы базы данных emp в таблицы PL/SQL
empno_tab и ename_tab:
PROCEDURE fetch_emp_data
(rows OUT BINARY_INTEGER,
empno_tab OUT EmpnoTabTyp,
ename_tab OUT EnameTabTyp,
...) IS
BEGIN
rows := 0;
FOR emprec IN (SELECT * FROM emp) LOOP
rows := rows + 1;
empno_tab(rows) := emprec.empno;
ename_tab(rows) := emprec.ename;
...
END LOOP;
END;
2-68 Руководство пользователя и справочник по PL/SQL
Однако нельзя ссылаться на таблицы PL/SQL в фразе INTO.
Например, следующее предложение SELECT незаконно:
PROCEDURE fetch_emp_data
(rows OUT BINARY_INTEGER,
empno_tab OUT EmpnoTabTyp,
ename_tab OUT EnameTabTyp,
...) IS
BEGIN
SELECT empno, ename
INTO empno_tab, ename_tab -- незаконно
FROM emp;
...
END;
Удаление строк
--------------
Не существует прямолинейного способа удаления строк из таблицы
PL/SQL, потому что предложение DELETE не может применяться для
этой цели. Присваивание строке пустого значения, показанное
ниже, не приводит к цели, потому что строка остается:
sal_tab(3) := NULL;
Последующее обращение к этой строке не приведет к исключению
NO_DATA_FOUND.
Хотя вы не можете удалять индивидуальных строк из таблиц PL/SQL,
есть простой способ удалять такие таблицы целиком. Прежде
всего, объявите еще одну таблицу PL/SQL того же типа, и оставьте
ее пустой. Позже, когда вы захотите удалить первоначальную
таблицу PL/SQL, просто присвойте ей пустую таблицу, как показано
в следующем примере:
DECLARE
TYPE NumTabTyp IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
sal_tab NumTabTyp;
empty_tab NumTabTyp;
...
BEGIN
/* Загрузить таблицу окладов. */
FOR i IN 1..50 LOOP
sal_tab(i) := i;
END LOOP;
...
/* Удалить все строки из таблицы окладов. */
sal_tab := empty_tab;
...
IF sal_tab(3) = 3 THEN ... -- возбуждает NO_DATA_FOUND
...
END;
Основы 2-69
----------------
Пользовательские записи
Вы можете использовать атрибут %ROWTYPE, чтобы объявить запись,
которая будет представлять строку таблицы базы данных, или
строку, извлекаемую курсором. Однако вы не можете
специфицировать типы полей в такой записи, или определить свои
собственные поля. Составной тип RECORD снимает эти ограничения.
Как вы могли ожидать, объекты типа RECORD называются ЗАПИСЯМИ.
В отличие от таблиц PL/SQL, записи имеют уникально поименованные
поля, которые могут принадлежать различным типам данных.
Например, предположим, что вы имеете различного рода данные о
сотруднике, такие как имя, оклад, дата приема и т.п. Эти данные
различаются по типам, но все они взаимосвязаны. Запись,
содержащая такие поля, как имя, оклад и дата приема сотрудника,
помогла бы вам обращаться с этими данными как с логической
единицей.
Объявление записей
------------------
Как и таблицы PL/SQL, записи должны объявляться за два шага.
Сначала вы объявляете (поименованный) тип RECORD, а затем
объявляете поьзовательские записи этого типа.
Вы можете объявлять типы RECORD в декларативной части любого
блока, подпрограммы или пакета, используя следующий синтаксис:
TYPE имя_типа IS RECORD
(имя_поля1 {тип_поля | переменная%TYPE | таблица.столбец%TYPE
| таблица%ROWTYPE} [NOT NULL],
(имя_поля2 {тип_поля | переменная%TYPE | таблица.столбец%TYPE
| таблица%ROWTYPE} [NOT NULL],
...);
Здесь имя_типа - спецификатор типа, используемый в последующих
объявлениях записей этого типа, а тип_поля - любой тип данных,
включая RECORD и TABLE. Альтернативно, вы можете использовать
атрибут %TYPE или %ROWTYPE, чтобы специфицировать тип данных для
поля. В следующем примере объявляется тип RECORD с именем
DeptRecTyp:
DECLARE
TYPE DeptRecTyp IS RECORD
(deptno NUMBER(2) NOT NULL := 20,
dname dept.dname%TYPE,
loc dept.loc%TYPE);
...
Заметьте, что объявления полей аналогичны объявлениям
переменных. Каждое поле имеет уникальное имя и специфический
тип данных. Вы можете добавить ограничение NOT NULL к
объявлению любого поля, и тем самым предотвратить присваивание
этому полю пустых значений. Поля, объявленные с ограничением
NOT NULL, должны быть инициализированы.
2-70 Руководство пользователя и справочник по PL/SQL
После объявления типа DeptRecTyp вы можете объявлять записи
этого типа, например:
dept_rec DeptRecTyp;
Идентификатор dept_rec представляет целую запись.
В отличие от таблиц PL/SQL, запись может быть инициализирована в
своем объявлении, как показывает пример:
DECLARE
TYPE TimeTyp IS RECORD
(second SMALLINT := 0,
minute SMALLINT := 0,
hour SMALLINT := 0);
...
Когда вы объявите запись типа TimeTyp, все три ее поля получат
нулевые начальные значения.
Пользовательские записи подчиняются обычным правилам сферы и
инстанциации. В пакете, записи инстанциируются при первом
обращении к этому пакету, и перестают существовать, когда вы
выходите из приложения или заканчиваете сессию базы данных. В
блоке или подпрограмме, записи инстанциируются при входе в блок
или подпрограмму, и перестают существовать, когда вы выходите из
блока или подпрограммы.
Как и скалярные переменные, пользовательские записи могут
объявляться как формальные параметры процедур и функций.
Пример:
PACKAGE emp_actions IS
TYPE EmpRecTyp IS RECORD
(empno NUMBER(4) NOT NULL := 1001,
ename CHAR(10),
job CHAR(14),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(4));
...
PROCEDURE hire_employee (emp_rec EmpRecTyp);
...
END emp_actions;
Чтобы определить поведение формальных параметров, вы используете
моды параметров, которые обсуждаются в главе 6. Параметры OUT
позволяют возвращать значения вызывающей программе при выходе из
подпрограммы. Если выход успешен, PL/SQL присваивает
фактическим параметрам значения строк. Однако, если вы выходите
с необработанным исключением, PL/SQL не присваивает фактическим
параметрам значения строк.
Основы 2-71
Обращение к записям
-------------------
Чтобы обращаться к индивидуальным полям в записи, вы используете
квалифицированные ссылки:
имя_записи.имя_поля
Например, вы обращаетесь к полю ename в записи emp_rec так:
emp_rec.ename ...
Вы можете присвоить конкретному полю записи значение выражения
PL/SQL, используя следующий синтаксис:
имя_записи.имя_поля := выражение_plsql;
В следующем примере имя сотрудника преобразуется в прописные
буквы:
emp_rec.ename := UPPER(emp_rec.ename);
Вместо присваивания значений отдельным полям записи можно
присвоить значения сразу всем полям в записи. Это можно сделать
двумя способами. Во-первых, вы можете присвоить одну запись
другой, если обе записи принадлежат одному и тому же типу.
Например, при объявлениях
DECLARE
TYPE DeptRecTyp IS RECORD (...);
dept_rec1 DeptRecTyp;
dept_rec2 DeptRecTyp;
...
следующее присваивание законно:
BEGIN
...
dept_rec1 := dept_rec2;
Во-вторых, вы можете присвоить записи список значений столбцов
при помощи предложения SELECT или FETCH, как показывает
следующий пример. Вы должны лишь обеспечить, чтобы имена
столбцов появлялись в том же порядке, что и поля в вашей записи.
DECLARE
TYPE DeptRecTyp IS RECORD
(deptno NUMBER(2),
dname CHAR(14),
loc CHAR(13));
dept_rec DeptRecTyp;
...
BEGIN
SELECT deptno, dname, loc INTO dept_rec FROM dept
WHERE deptno = 30;
...
END;
2-72 Руководство пользователя и справочник по PL/SQL
Ограничения
Даже при полном совпадении полей, записи различного типа нельзя
присваивать друг другу. Более того, пользовательская запись и
запись %ROWTYPE всегда принадлежат различным типам, как
показывает следующий пример:
DECLARE
TYPE DeptRecTyp IS RECORD
(deptno NUMBER(2),
dname CHAR(14),
loc CHAR(13));
dept_rec1 DeptRecTyp;
dept_rec2 dept%ROWTYPE;
...
BEGIN
...
dept_rec1 := dept_rec2; -- незаконно
Нельзя присваивать записи список значений, используя оператор
присваивания. Так, следующий синтаксис незаконен:
имя_записи := (значение1,значение2, значение3, ...); --незаконно
Кроме того, записи нельзя проверять на равенство или
неравенство. Например, следующее условие IF незаконно:
IF dept_rec1 = dept_rec2 THEN -- незаконно
...
END IF;
Основы 2-73
Вложенные записи
----------------
PL/SQL позволяет вам объявлять и ссылаться на ВЛОЖЕННЫЕ записи.
Иными словами, запись может быть компонентой другой записи, как
показывает следующий пример:
DECLARE
TYPE TimeTyp IS RECORD
(minute SMALLINT,
hour SMALLINT);
TYPE MeetingTyp IS RECORD
(day DATE,
time TimeTyp, -- вложенная запись
place CHAR(20),
purpose CHAR(50));
TYPE PartyTyp IS RECORD
(day DATE,
time TimeTyp, -- вложенная запись
loc CHAR(15));
meeting MeetingTyp;
seminar MeetingTyp;
party PartyTyp;
...
BEGIN
meeting.day := '26-JUN-91';
meeting.time.minute := 45;
meeting.time.hour := 10;
...
END;
Следующий пример показывает, что вы можете присваивать одну
вложенную запись другой, если обе они принадлежат одному типу:
seminar.time := meeting.time;
Такие присваивания разрешаются даже в тех случаях, когда
содержащие записи относятся к разным типам данных, как
показывает следующий пример:
party.time := meeting.time;
2-74 Руководство пользователя и справочник по PL/SQL
Преимущества записей
--------------------
Тип RECORD позволяет вам коллекционировать информацию об
атрибутах объекта. Такой информацией легко манипулировать,
потому что вы можете ссылаться на объект в целом. В следующем
примере, вы собираете бухгалтерские цифры из таблиц базы данных
с именами assets и liabilities, а затем применяете сравнительный
анализ, чтобы сравнить производительность двух дочерних
компаний:
DECLARE
TYPE FiguresTyp IS RECORD
(cash REAL,
marketable_securities REAL,
accounts_receivable REAL,
inventories REAL,
accounts_payable REAL,
notes REAL,
employment_costs REAL,
accrued_taxes REAL,
dividends_payable REAL,
short_term_debt REAL);
sub1_figs FiguresTyp;
sub2_figs FiguresTyp;
...
FUNCTION acid_test (figs FiguresTyp) RETURN REAL IS
current_liabilities REAL;
BEGIN
current_liabilities := figs.accounts_payable +figs.notes
+ figs.employment_costs + figs.accrued_taxes
+ figs.dividends_payable + figs.short_term_debt;
RETURN (figs.cash + figs.marketable_securities
+ figs.accounts_receivable) / current_liabilities;
END acid_test;
...
BEGIN
SELECT cash, mkt_sec, accts_rec, ... INTO sub1_figs
FROM assets, liabilities
WHERE assets.sub = 1 AND liabilities.sub = 1;
SELECT cash, mkt_sec, accts_rec, ... INTO sub2_figs
FROM assets, liabilities
WHERE assets.sub = 2 AND liabilities.sub = 2;
...
IF acid_test(sub1_figs) > acid_test(sub2_figs) THEN ...
...
END;
Заметьте, как легко передать собранные цифры функции acid_test,
которая вычисляет финансовый коэффициент.