ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ PL/SQL БАЗЫ ДАННЫХ

advertisement
БЕЖАНИШВИЛИ ЛОЛИТА
ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ
PL/SQL БАЗЫ ДАННЫХ ORACLE
(часть I)
`ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ”@
ГРУЗИНСКИЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
Л. Бежанишвили
ПРОГРАММИРОВАНИЕ НА ЯЗЫКЕ
PL/SQL БАЗЫ ДАННЫХ ORACLE
(часть I)
Регистрировано редакционноиздательским советом ГТУ
Тбилиси
2009
УДК 004.432.2; 004.655
Данная книга посвящена изучению основ языка PL/SQL, который
широко применяется для программирования в базах данных Oracle.
Рассмотрены основные управляющие структуры языка, вопросы,
связанные с созданием и применением курсоров, использованием
DML в программах на PL/SQL, а также пакетов процедур и функций.
Настоящее пособие содержит часть лекционного материала по
дисциплине «Системы управления базами данных», читаемого в
Грузинском Техническом Университете
и
предназначено для
магистрантов, а также специалистов разных областей, которые в своей
профессиональной деятельности используют базы данных Oracle.
Предварительные знания: основы реляционных баз данных;
непроцедурно-ориентированный язык SQL; основы
процедурноориентированного программирования.
Р е ц е н з е н т:
Г.Сургуладзе, доктор технических наук, профессор
© Издательский дом "Технический университет", 2009
ISBN 978-9941-14-504-9 (все части)
ISBN 978-9941-14-505-6 (часть первая)
http://www.gtu.ge/publishinghouse/
Все права защищены. Ни одна часть этой книги (будь то текст, фото, иллюстрация или
др.) не может быть использована без письменного разрешения издателя ни в каких-либо
форме и средствах (электронной или механической).
Нарушение авторских прав карается законом.
Оглавление
Введение .................................................................................. 4
1. Основы языка ............................................................... 4
1.1. Структура программы PL/SQL............................... 4
1.2. Анонимные блоки...................................................... 5
1.3. Именованные блоки .................................................. 7
1.4. Вложенные блоки ...................................................... 8
1.5. Набор символов PL/SQL........................................... 9
1.6. Идентификаторы ....................................................... 9
1.7. Обзор основных типов данных PL/SQL .............. 10
1.7.1. Числовые типы данных..................................... 10
1.7.2. Символьные типы данных ............................... 12
1.7.3. Основные типы данных даты и времени....... 13
1.7.4. Большие объекты (LOB) данных.................... 14
1.7.5. Тип данных BOOLEAN..................................... 15
1.8. Объявление переменных ........................................ 15
1.9. Использование %TYPE .......................................... 17
1.10 Выражения................................................................ 19
1.11. Комментарии........................................................... 20
2. Управляющие структуры PL/SQL......................... 22
2.1. Оператор присваивания......................................... 22
2.2. Оператор IF............................................................... 22
2.3. Оператор CASE ....................................................... 26
2.4. Операторы GOTO и метки ..................................... 31
2.5. Циклы ........................................................................ 32
3. DML в PL/SQL
3.1 Курсоры...................................................................... 35
3.2 Курсоры с параметрами.......................................... 38
3.3 Курсорный цикл FOR ............................................. 39
4. Обработка ошибок в PL/SQL
5. Хранимые процедуры и функции.............................. 45
5.1. Процедуры................................................................. 45
5.2. Функции .................................................................... 46
6. Пакеты ............................................................................. 51
Л и т е р а т у р а .................................................................. 56
3
Введение
PL/SQL — это аббревиатура от Procedural Language
extensions to the Structured Query Language, что в переводе с
английского означает «процедурные языковые расширения
для SQL».
SQL
представляет собой
повсеместно
распространенный язык формирования запросов, с помощью
которых можно получать и обновлять информацию в
реляционных базах данных.
PL/SQL был разработан
компанией
Oracle Corporation с целью преодоления
некоторых ограничений SQL и обеспечения разработчиков
приложений баз данных Oracle более совершенным
инструментарием для программирования.
1.
Основы языка
1.1. Структура программы PL/SQL
В
PL/SQL
фундаментальной
организационной
программной единицей является блок. Он лежат в основе
двух ключевых концепций.
• Модульность. Блок PL/SQL является базовой
единицей кода. Из данных единиц создаются модули
(например, процедуры и функции), которые, в свою
очередь, составляют приложение.
•
Область действия. Блок определяет область действия
или контекст логически связанных объектов. В блоке
группируются связанные между собой объявления и
выполняемые операторы.
4
Блок может быть анонимным (то есть не имеющим
имени) или именованным (представляющим собой процедуру
и функцию).
Блок PL/SQL может содержать до четырех разделов,
однако только один из них является обязательным.
• Заголовок. Используется только в именованных
блоках, определяются тип блока (процедура,
функция) и способ его вызова.
•
•
•
Раздел объявлений. Объявляются все переменные и
другие объекты PL/SQL, используемые в этом блоке
(например, вложенные блоки, на которые имеются
ссылки в исполняемом блоке и блоке исключений).
Исполняемый раздел. Операторы, которые выполняются ядром PL/SQL во время работы приложения.
Раздел исключений. Обрабатывает исключения
(предупреждения и ошибки).
Ниже приведена структура блока PL/SQL. Квадратные
скобки указывают на необязательную часть синтаксиса.
[Заголовок ]
[Раздел объявлений ]
BEGIN
Исполняемый раздел
[EXCEPTION
Раздел исключений]
END;
1.2. Анонимные блоки
В анонимном блок PL/SQL вообще нет раздела
заголовка, блок начинается ключевым словом DECLARE (или
BEGIN):
5
Исполняемый раздел
(вывод текста)
BEGIN
…
DBMS_OUTPUT.PUT_LINE (‘Hello world’);
END;
Анонимный блок не может быть вызван другим
блоком, поскольку не имеет составляющей, с помощью
которой к нему можно обратиться. Таким образом, он
является чем-то вроде сценария, который предназначен для
выполнения операторов PL/SQL, в большинстве случаев
включающих вызовы процедур и функций.
Поскольку анонимные блоки могут содержать
собственные
разделы
объявлений
и
исключений,
разработчики часто используют их для определения области
видимости идентификаторов и области действия обработки
исключений в программе большего размера. Эти свойства
блока мы подробно рассмотрим в следующих разделах.
Структура анонимного блока
Общий формат анонимного блока PL/SQL таков:
[ DECLARE
... необязательные операторы объявлений ... ]
BEGIN
... исполняемые операторы ...
[ EXCEPTION
... необязательные операторы обработки исключений ... ]
END;
6
Ключевые
слова
BEGIN
и
END
являются
обязательными, и между ними должен быть как минимум
один исполняемый оператор.
Примеры анонимных блоков
Ниже приведены различные сочетания разделов,
которые допустимы для блока PL/SQL. Анонимный блок
BEGIN … END без разделов объявлений и исключений:
Вывод текущей даты в
стандартном формате
BEGIN
…
DBMS_OUTPUT.PUT_LINE (SYSDATE);
END;
Анонимный блок с разделом объявлений, но без
раздела исключений:
DECLARE
v_time_now DATE := SYSDATE;
BEGIN
…
DBMS_OUTPUT.PUT_LINE (v_time_now);
END;
1.3. Именованные блоки
Хотя анонимные блоки PL/SQL применяются во
многих приложениях Oracle, вероятно, большая часть
написанного вами кода будет оформлена в виде именованных
7
блоков. Их
заголовка:
главной
особенностью
является
наличие
PROCEDURE calc_totals IS
year_total NUMBER;
BEGIN
year_total := 0;
…
END;
1.4.
Вложенные блоки
Вложенным является блок, который располагается
внутри другого блока. Вложенный блок, в свою очередь,
также может содержать блок. Таким образом, допустимой
является структура вложенных блоков представленная на
рис. 1.
DECLARE
...
BEGIN
DECLARE
total_sales NUMBER;
BEGIN
DECLARE
hiredate DATE;
BEGIN
…
END;
END;
END;
Рис. 1. Вложенные анонимные блоки
8
Вложенный блок PL/SQL называют также дочерним
или подблоком, а внешний блок — родительским.
1.5.
Набор символов PL/SQL
Программа
PL/SQL
представляет
собой
последовательность операторов, состоящих из одной или
нескольких строк текста. Набор символов, из которых можно
составлять эти строки текста, зависит от используемого в
базе данных набора символов. Для примера в табл. 1
приведены символы, входящие в набор ASCII.
Таблица 1. Символы из набора ASCII, которые можно
использовать в PL/SQL.
Тип
Символы
Буквы
A-Z, а-z
Цифры
0-9
Знаки
~!@#$%*()_-+=|[]{}:;”' <>,?/^
Пробельные Табуляция,
пробел,
новая
строка,
символы
возврат каретки
Каждое ключевое слово в PL/SQL состоит из разных
комбинаций символов данного набора. По умолчанию язык
SQL не чувствителен к регистру символов. Это означает, что
символы верхнего регистра в нем интерпретируются так же,
как символы нижнего, за исключением ситуаций, когда
символы заключены в одинарные кавычки, что превращает
их в литеральные строки.
1.6.
Идентификаторы
Идентификатор (переменная) — это имя объекта
PL/SQL, которым может быть:
9
константа; скалярная переменная; составная переменная
(запись или коллекция);
исключение; процедура; функция; пакет; тип; курсор;
зарезервированное слово; метка.
К идентификаторам PL/SQL предъявляются следующие
требования:
• длина - до 30 символов;
• должны начинаться с буквы;
• не должны содержать пробелов (но могут
включать символы «$», «_» и «#»).
Примеры допустимых имен идентификаторов:
company_id#
primary_acct_responsibility
First_name
FirstName
Address_line1
S123456
1.7. Обзор основных типов данных
PL/SQL
При
объявлении
переменной
или
константы
необходимо определить ее тип данных. В PL/SQL определен
широкий набор скалярных и составных типов данных.
1.7.1.
Числовые типы данных
В PL/SQL имеются как действительные, так и
целочисленные типы данных. В их основе лежат три типа
NUMBER, PLS_INTEGER, BINARY_INTEGER.
В программах встречаются и другие числовые типы
данных, например FLOAT и DECIMAL, но по сути они
10
представляют собой альтернативные имена перечисленных
базовых типов данных. Все они, как-правило, основаны на
одном базовом типе NUMBER. Некоторые основные
числовые типы приведены в таблице 2:
Тип данных
NUMBER(P, S)
NUMERIC (P, S)
DEC(P, S)
DECIMAL(P, S)
}
Диапазон
значений
P – колеблется
от 1 до 38.
S – колеблется
от -84 до 127.
то же, что
Number(p,s)
Примечание
где P (precision) –
точность
и S (scale) – масштаб.
Например, number (7,2)–
представляет собой число,
которое включает 5 цифр
до десятичной точки и 2
цифры после десятичной
точки.
NUMBER
}
INTEGER
INT
SMALLINT
то же ,
что
Number
REAL
FLOAT
±[0 ÷ 9.99E125]
Real – точность Числа с плавающей
до 19 десятичных запятой
знаков
Float – точность
до 38 десятичных
знаков
BINARY_INTEGER
-2 147 483 648 ÷
+2 147 483 647
Позволяет хранить
целые числа со знаком в
двоичном формате
( только в PL/SQL)
PLS_INTEGER
-2 147 483 648 ÷
+2 147 483 647
Целое со знаком
(только в PL/SQL)
Таблица 2. Некоторые основные числовые типы данных
11
1.7.2.
Символьные типы данных
PL/SQL поддерживает строки фиксированной и
переменной длины, состоящие как из традиционных
символов, так и из символов Unicode. К строкам первого вида
относятся строки типов CHAR и NCHAR, а к строкам
второго вида — типов VARCHAR2 и NVARCHAR2.
Тип данных
Размер
Примечание
CHAR (размер)
Максимальный размер Строки
– 2000 байт.
фиксированной
длины.
NCHAR (размер)
Максимальный размер Строки
– 2000 байт.
фиксированной
длины (UNICODE)
VARCHAR2 (размер)
Максимальный размер Строки переменной
– 4000 байт.
длины
NVARCHAR2 (размер)
Максимальный размер Строки переменной
– 4000 байт.
длины (UNICODE)
LONG
Максимальный размер Строки переменной
– 2 ГБ.
длины
RAW
Максимальный размер Двоичные строки
– 2000 байт.
переменной длины
LONG RAW
Максимальный размер Двоичные строки
– 2 ГБ.
переменной длины
Таблица 3. Символьные типы данных
12
1.7.3.
Тип данных
Основные типы данных даты и
времени
Диапазон
Примечание
DATE
Дата от 1 января
4712 г. до н.э. и 31
декабря, 9999 года.
TIMESTAMP [(
точность)]
точность должна
быть числом от 0 до
9 (по умолчанию
является 6)
Значение параметра точность определяет количество
десятичных цифр,
выделенное для
хранения значений
долей секунды.
Включает в себя год,
месяц, день, час, минуту и
секунду.
точность должна
быть числом от 0 до
9 (по умолчанию
является 6)
Включает в себя год,
месяц, день, час, минуту и
секунду с часовым
поясом
TIMESTAMP [(
точность)] WITH
TIME ZONE
Например: TIMESTAMP
(6)
Например:
TIMESTAMP (5) WITH
TIME ZONE
INTERVAL YEAR
точность_лет
Позволяет определить
[(точность_лет)] это число цифр в
интервал времени в годах
TO MONTH
году (по умолчанию и месяцах
2)
Например:
INTERVAL YEAR (4) TO
MONTH
Таблица 4. Некоторые типы данных даты и времени
13
1.7.4.
Тип данных
Большие объекты (LOB)
данных
Размер
Примечание
BFILE
Переменная этого типа
Максимальны содержит локатор файла,
й размер
указывающий на файл
файла - 4 ГБ. операционной системы,
хранящийся вне базы данных.
Oracle интерпретирует
содержимое данного файла как
двоичные данные.
BLOB
Хранит до 4
Гб двоичных
данных.
Переменная этого типа
содержит локатор,
указывающий на большой
двоичный объект, хранящийся в
базе данных.
CLOB
Хранит до 4
Гб текстовых
данных.
Переменная этого типа
содержит локатор LOB,
указывающий на хранящийся
внутри базы данных большой
блок текстовых данных.
NCLOB
Хранит до 4
Гб текстовых
(UNICODE)
данных.
Большой символьный объект,
который поддерживает
средства работы с символами
различных языков. Переменная
этого типа содержит локатор
LOB, указывающий на
хранящийся внутри базы данных
большой блок текстовых
данных.
Таблица 5. Большие объекты данных (LOB)
14
1.7.5. Тип данных BOOLEAN.
PL/SQL поддерживает логический (булев) тип данных
— BOOLEAN. Переменные этого типа могут принимать одно
из трех значений - TRUE, FALSE или NULL - и позволяют
писать понятный, легко читающийся код даже в случаях,
когда он содержит очень сложные логические выражения.
1.8. Объявление переменных
Переменные определяются в разделе объявлений
блока. Общий синтаксис объявления переменных:
имя_переменной тип [CONSTANT] [NOT NULL] [:=
значение};
где имя_переменной — это имя переменной,
тип — это тип переменной, а значение —
начальное значение переменной.
Ниже приведены примеры корректного объявления
переменных:
DECLARE
v_description VARCHAR2(50);
v_number
NUMBER := 45;
v_counter
BINARY_INTEGER := 0;
В качестве имени переменной может быть использован
любой разрешенный идентификатор PL/SQL. Типы
VARCHAR2, NUMBER и BINARY_INTEGER – допустимые
типы PL/SQL. В этом примере для переменных v_number и
v_counter заданы начальные значения соответственно 45 и 0.
Если
начальное
значение
переменной,
например
v_description, не задано (она не инициализирована), по
умолчанию ей присваивается NULL. Если в объявлении
15
указано
NOT
NULL,
переменная
должна
быть
инициализирована.
Более того, переменной, которая описана как NOT
NULL, запрещается присваивать NULL при ее объявлении, в
выполняемом разделе или в разделе исключительных
ситуаций блока. Объявление, приведенное ниже, неверно, так
как переменная v_temp определена как NOT NULL, но не
инициализирована:
DECLARE
v_temp NUMBER NOT NULL;
Это можно исправить, если присвоить v_temp значение
по умолчанию, например:
DECLARE
v_temp NUMBER NOT NULL := 0;
Если в объявлении переменной указано CONSTANT,
то она должнабыть инициализирована и ее начальное
значение не может быть переменной "только для чтения".
Константы часто используются для хранения тех значений,
которые известны к моменту создания блока, например:
DECLARE
c_ID CONSTANT NUMBER(5) := 10000;
При желании вместо := можно воспользоваться
ключевым словом DEFAULT (по умолчанию). Например:
DECLARE
v_number NUMBER DEFAULT 45;
v_counter BINARY_INTEGER DEFAULT 0;
v_FirstName VARCHAR2(20) DEFAULT 'Scott’;
В разделе объявлений в одной строке может быть
описана только одна переменная. Нижеприведенный раздел
16
неверен, так как в одной и той же строке объявляются две
переменные:
DECLARE
v_FirstName, v_LastName VARCHAR2(20);
Корректный вариант этого блока:
DECLARE
v_FirstName VARCHAR2(20);
v_LastName VARCHAR2(20);
Во многих языках программирования не указывается,
что содержится в неинициализированных переменных. Во
время выполнения программы в таких переменных могут
оказаться случайные либо неизвестные значения. Это
считается
некорректным
стилем
программирования;
рекомендуется инициализировать переменные, если их
значения могут быть определены. В PL/SQL информация,
содержащаяся
в
неинициализированной
переменной,
определяется — такой переменной присваивается NULL.
Значение NULL означает "пропущенное или неизвестное
значение", поэтому вполне логично, что NULL по умолчанию
присваивается любой неинициализированной переменной в
PL/SQL.
1.9. Использование %TYPE
Во многих случаях для работы с данными, хранимыми
в таблицах базы данных, используются переменные PL/SQL.
При этом переменной, работающей с некоторым столбцом,
следует присваивать тип, соответствующий типу столбца.
Например, столбец first_name таблицы students имеет тип
17
VARCHAR2(20). С учетом этого можно объявить переменную
следующим образом:
DECLARE
v_FirstName VARCHAR2(20);
Посмотрим, что произойдет, если описание столбца
first_name
изменится.
Предположим,
что
таблица
модифицирована и столбец first_name имеет теперь тип
VARCHAR2(25). Текст программы PL/SQL, в которой
используется этот столбец, должен быть изменен:
DECLARE
v_FirstName VARCHAR2(25);
Если программа PL/SQL велика, этот процесс может
занять много времени, и, кроме того, существует большая
вероятность внесения ошибки. В этом случае вместо
жесткого задания типа переменной можно воспользоваться
атрибутом %TYPE. Он добавляется к ссылке на столбец
таблицы или к другой переменной и возвращает ее тип.
Например:
DECLARE
v_FirstName students.first_name%TYPE;
При использовании %TYPE переменная v_FirstName
будет иметь тот тип, который присвоен столбцу first_name
таблицы students. Тип определяется всякий раз, когда данный
блок выполняется для анонимных и именованных блоков и
когда компилируются хранимые объекты (процедуры,
функции и т.д.). %TYPE может быть также использован с
переменными PL/SQL, объявленными ранее. Приведенный
ниже пример иллюстрирует различные варианты применения
атрибута %TYPE:
18
DECLARE
v_room_id
v_office_id
classes.room_id%TYPE;
v_room_id%TYPE;
Если атрибут %TYPE применяется для переменной
(столбца), которая (который) содержит ограничение NOT
NULL (например, classes.room_id ), то возвращаемый тип не
имеет этого ограничения. Приведенный выше блок вполне
корректен, хотя переменные v_room_id, v_office_id
не
инициализированы. Дело в том, что эти переменные могут
содержать NULL-значения. Использование атрибута %TYPE
считается хорошим стилем программирования, так как при
этом программы PL/SQL становятся гибче и проще
адаптируются к изменению различных параметров,
задаваемых в базе данных.
1.10. Выражения
Использование выражения PL/SQL как самостоятельного оператора бессмысленно — оно должно быть
элементом оператора. Например, выражение может
находиться в правой части операции присваивания или быть
элементом SQL-оператора. Тип выражения определяют
составляющие его операции и типы операндов. Операнд —
это аргумент операции. В операциях PL/SQL используется
либо один аргумент (унарная, или одноместная, операция),
либо два аргумента (бинарная, или двухместная, операция).
Например, операция отрицания (-) является унарной, а
операция умножения (*) — бинарной. Приоритет операций
выражения определяет порядок их выполнения.
19
Таблица 6. Операции PL/SQL.
Операторы
Тип
Описание
NOT
Унарный
+, -
Унарные
*, /
Бинарные
Логическое
отрицание
Тождественность,
отрицание
Умножение, деление
+, -, ||
Бинарные
=, !=, <, >, <=,
>=, IS NULL,
LIKE,
BETWEEN, IN
AND
Бинарные (за
исключением
IS NULL,
который является
унарным)
Бинарный
OR
Бинарный
Сложение, вычитание,
конкатенация строк
Операции сравнения
Логическое «И»
Логическое «ИЛИ»
1.11. Комментарии
Наличие поясняющего и сопроводительного текста в
коде (комментариев) является основным признаком хорошей
программы. PL/SQL предлагает разработчикам две
разновидности
комментариев:
однострочные
и
многострочные.
Однострочные комментарии начинаются двумя
дефисами (--), между которыми не должно быть пробелов
или каких-либо других символов. Весь текст после двух
дефисов и до конца строки рассматривается как комментарий
и игнорируется компилятором. Если два дефиса стоят в
начале строки, комментарием считается вся строка.
20
Запомните: два дефиса отмечают как комментарий
остаток строки в редакторе кода, а не всю инструкцию
PL/SQL, после которой они стоят. Например, следующем
операторе IF с помощью однострочного комментария
поясняется содержимое условного выражения:
IF salary<min_salary (20) --Функция min_salary возвращает
минимальную годовую зарплату
THEN
salary := salary + salary *0.25;
END IF;
Многострочные комментарии. Если однострочные
комментарии удобны для создания кратких замечаний к
фрагменту кода или для временного исключения строки
программы из обработки, то многострочные позволяют
включать в программу длинный сопроводительный текст или
пояснения.
Многострочный комментарий помещается между
начальным (/*) и конечным (*/) ограничителями. Весь текст
между этими двумя парами символов рассматривается как
часть комментария и игнорируется компилятором. В
следующем
примере
многострочный
комментарий
располагается в разделе заголовка процедуры:
PROCEDURE calc_sum (company_id IN NUMBER) IS
/*
Имя программы: calc_sum
Автор.- ...
Программа предназначена для …
Для работы программы требуется: …
*/
BEGIN
…
END;
21
2.
Управляющие структуры
PL/SQL
В
этой
главе
рассматриваются
основы
программирования и структура программных операторов
PL/SQL, в частности описываются условные операторы (IF и
CASE), циклы и методы обработки исключений.
2.1. Оператор присваивания
Основной операцией является операция присваивания
(assignment). Ее синтаксис таков:
переменная := выражение;
Данная операция может производиться в выполняемом
разделе и в разделе исключительных ситуаций блока. Ниже
приводится ряд примеров использования операции
присваивания:
DECLARE
v_String1 VARCHAR2(10);
v_String2 VARCHAR2(15);
v_Numeric NUMBER;
BEGIN
v_String1 := 'Hello';
v_Strlng2 := v_String1;
v_Numeric := -12.4;
END;
2.2. Оператор IF
В программах очень часто приходится реализовывать
выполнение тех или иных операций в зависимости от
определенных условий, например:
22
•
если оклад находится в пределах от десяти до
двадцати тысяч долларов, назначить бонус в размере
1500 долларов;
• если в пределах от двадцати до сорока тысяч – в
размере 1000 долларов;
• а если он превышает сорок тысяч долларов – в
размере 500 долларов;
Операторы IF позволяют реализовать в программе
условную логику. Как следует из представленной ниже
таблицы 7, они бывают трех видов.
Тип
оператора IF
Описание
IF … THEN
….
END IF;
Это простейшая форма оператора IF.
Условие, содержащееся между
ключевыми словами IF и THEN, определяет,
должна ли выполняться группа операторов,
находящаяся между THEN и END IF. Если
результат проверки условия равен FALSE, то
данный код не обрабатывается
Конструкция реализует логику «или-или». В
зависимости от условия,
заданного между ключевыми словами IF и
THEN, выполняется либо код, находящийся
между THEN и ELSE, либо код между ELSE и
END IF. Но в любом случае реализуется
только одна из двух групп исполняемых
операторов
Эта последняя, и самая сложная, форма
оператора IF выбирает действие на основе
набора взаимоисключающих условий и
выполняет соответствующую группу
исполняемых операторов.
IF … THEN
…
[ELSE
…]
END IF;
IF … THEN
…
[ELSIF
…]
[ELSE
…]
END IF;
23
Конструкция IF...THEN
Общий синтаксис конструкции IF...THEN таков:
IF условие THEN
... последовательность исполняемых операторов ...
END IF;
Здесь условие – это логическая переменная, константа
или логическое выражение, результатом проверки которого
является возвращаемое значение TRUE, FALSE или NULL.
Исполняемые операторы, расположенные между ключевыми
словами THEN и END IF, выполняются, если результат
проверки условия равен TRUE, и не выполняются - если он
равен FALSE или NULL.
Следующий условный оператор IF сравнивает два
различных числовых значения. Учтите, что если одно из них
равно NULL, тогда все выражение возвращает NULL (и в
данном случае бонус не назначается).
Например:
IF salary > 40000 THEN
give_bonus(employee_id,
назначения бонуса*/
END IF;
500);
/*вызов
функции
Конструкция IF...THEN...ELSE
Конструкция IF.. .THEN.. .ELSE применяется в случаях,
когда нужно выбрать одно из двух взаимоисключающих
действий. Формат этой версии оператора IF таков:
IF условие THEN
... последовательность операторов, выпопняеных в случае,
когда результат
24
проверки условия равен TRUE . . .
[ELSE
... последовательность операторов, выпопняеных в случае,
когда результат
проверки условия равен FALSE или NULL ... ]
END IF;
Здесь условие – это логическая переменная, константа
или логическое выражение. Если его значением является
TRUE, выполняются операторы, расположенные между
ключевыми словами THEN и ELSE, а если таковым служит
операторы,
FALSE
или
NULL,
то
выполняются
расположенные между ключевыми словами ELSE и END IF.
Вот пример конструкции IF.. .THEN.. .ELSE:
IF salary > 40000 THEN
give_bonus(employee_id, 500);
ELSE
give_bonus(employee_id, 0);
END IF;
Конструкция IF...THEN...ELSIF
Данная форма оператора IF полезна в тех случаях,
когда реализуется логика со многими альтернативными
действиями; это уже не ситуация «или-или». Вот как
записывается ряд взаимоисключающих альтернатив:
IF условие 1 THEN
операторы_1
[ELSIF усповие_n
операторы_n]
[ELSE
операторы_else]
END IF;
25
В каждом предложении ELSIF за условием должно
следовать ключевое слово THEN, а наличие ELSE не является
обязательным. Последнее ключевое слово, если оно вообще
используется, ставится в конце конструкции IF.. .THEN...
ELSIF и означает «если неверно все вышеперечисленное». То
есть когда ни одно из условий не равно TRUE, выполняются
операторы, следующие за ELSE. Если же ключевое слово
ELSE отсутствует, все исполняемые блоки конструкции IF..
.THEN.. .ELSIF игнорируются.
IF salary >= 10000 and salary <= 20000 THEN
give_bonus(employee_id, 1500);
ELSIF salary > 20000 and salary <= 40000 THEN
give_bonus(employee_id, 1000);
ELSIF salary > 40000 THEN
give_bonus(employee_id, 500);
ELSE
give_bonus(employee_id, 0);
END IF;
2.3. Оператор CASE
Операторы CASE позволяют выбрать для выполнения
одну из нескольких последовательностей исполняемых
операторов. Oracle поддерживаются два типа операторов
CASE:
•
простой оператор CASE — связывает одну или
несколько последовательностей операторов PL/SQL с
соответствующим значением (последовательность
для выполнения выбирается с учетом результатов
вычисления выражения, возвращающего указанное
значение);
26
•
поисковый оператор CASE — выбирает для
выполнения одну из последовательностей операторов
в зависимости от результатов вычисления списка
логических
условий
(выполняется
последовательность операторов, связанная с первым
условием, результат проверки которого оказался
равным TRUE).
В дополнение к операторам CASE
PL/SQL
поддерживает CASE-выражения. Выражение CASE очень
похоже на оператор CASE, оно позволяет выбрать для
вычисления одно или несколько выражений. В итоге
получается одно значение, тогда как результатом работы
оператора CASE является выполнение последовательности
операторов PL/SQL.
Простой оператор CASE
Простой оператор CASE позволяет выбрать для
выполнения одну из нескольких последовательностей
операторов PL/SQL в зависимости от результата вычисления
одного выражения. Он имеет следующую форму записи:
CASE выражение
WHEN результат_1 THEN
операторы_1
WHEN результат_2 THEN
операторы_2
…
[ELSE
Операторы_else]
END CASE;
27
Ветвь ELSE здесь не обязательна. При выполнении
такого оператора PL/SQL сначала вычисляет выражение.
Затем результат сравнивается со значением результат_1.
Если они совпадают, то выполняются операторы_1, в
противном случае проверяется значение результат_2 и т. д.
Приведем пример простого оператора CASE, в котором
в качестве основы для выбора подходящего алгоритма
вычисления бонуса используется значение переменной
employee_type:
CASE employee_type
WHEN 'S' THEN
salary_bonus(employee_id);
WHEN 'H' THEN
hourly_bonus(employee_id);
WHEN ‘C' THEN
commissioned_bonus(employee_id);
ELSE
RAISE invalid_employee_type;
END CASE;
Поисковый оператор CASE
Как вы, возможно, догадываетесь, поисковый оператор
CASE (searched CASE) проверяет набор логических
выражений и, обнаружив выражение, равное TRUE,
выполняет последовательность связанных с ним операторов.
По сути дела, это эквивалент оператора CASE, пример
которого приведен в предыдущем разделе.
Поисковый оператор CASE имеет следующую форму
записи:
CASE
WHEN выражение_1 THEN
28
операторы_1
WHEN выраженис_2 THEN
операторы_2
[ELSE
опeрaторы_else]
END CASE;
Он прекрасно
назначения бонуса:
подходит
для
реализации
логики
CASE
WHEN salary >= 10000 AND salary <= 20000 THEN
give_bonus(employee_id, 1500);
WHEN salary > 20000 AND salary <= 40000 THEN
give_bonus(employee_id, 1000);
WHEN salary > 40000 THEN
give_bonus(employee_id, 500);
ELSE
give_bonus(employee_id, 0);
END CASE;
Поисковый оператор CASE, равно как и простой
оператор с этим же именем, действует в соответствии со
следующими правилами.
•
•
•
Работа оператора заканчивается сразу же после
исполняемых
выполнения
последовательности
операторов, связанных с истинным выражением. Если
истинными оказываются несколько выражений,
выполняются операторы, связанные с первым из них.
Ключевое слово ELSE не обязательно. Если оно не
задано и ни одно из выражений не оказалось равным
TRUE, инициируется исключение CASE_NOT_FOUND.
Условия WHEN проверяются по порядку, сверху вниз.
29
Выражение CASE
Выражения CASE выполняют ту же задачу, что и
операторы CASE, но только не для исполняемых операторов,
а для выражений. Простое выражение CASE позволяет
выбрать для вычисления одно из нескольких выражений на
основе заданного скалярного значения. Поисковое
выражение CASE последовательно вычисляет выражения из
заданного списка, пока одно из них не окажется равным
TRUE, а затем возвращает результат связанного с ним
выражения. Приведем синтаксис этих двух видов выражения
CASE:
Простое_выражеиие_Саsе :=
CASE выражение
WHEN результат_1 THEN
результирующее_выражение_1
WHEN результат_2 THEN
результирующее_выражение_2
ELSE
результирующее_выражение_else
END;
Поисковое_выражение Case :=
CASE
WHEN выражение_1 THEN
результирующее_выражение_1
WHEN выражение_2 THEN
результирующее_выражение_2
ELSE
Результирующее_выражение_else
END;
30
Выражение CASE возвращает одно значение –
результат выбранного для вычисления выражения. Каждой
ветви WHEN должно быть поставлено в соответствие одно
результирующее выражение (но не оператор). В конце
выражения CASE не нужно ставить ни точку с запятой, ни
ключевые слова END CASE. Выражение CASE оканчивается
единственным оператором END.
Например:
bonus_amount :=
CASE
WHEN salary >= 10000 AND salary <= 20000 THEN 1500
WHEN salary > 20000 AND salary <= 40000 THEN 1000
WHEN salary > 40000 THEN 500
ELSE 0
END;
В отличие от оператора CASE, в том случае, если ни
одна из ветвей WHEN не выбрана, выражение CASE не
генерирует ошибку, а просто возвращает NULL.
2.4. Операторы GOTO и метки
В языке программирования PL/SQL имеется оператор
GOTO (перейти к). Его синтаксис:
GOTO метка;
где метка — это метка, определяемая в блоке PL/SQL.
Метки заключаются в двойные угловые скобки. При
выполнении оператора GOTO управление программой сразу
же передастся оператору, на который указывает метка.
Представим рассматриваемый пример цикла следующим
образом:
31
DECLARE
v_Counter BINARY_INTEGER := 1;
BEGIN
LOOP
INSERT INTO temp_table VALUES (v_Counter, ' Loop
count');
v_Counter := v_Counter + 1;
IF v_Counter > 50 THEN
GOTO l_EndOfLoop;
END IF;
END LOOP;
«l_EndOfLoop» ;
END;
В PL/SQL на использование операторов GOTO
налагаются определенные ограничения. Нельзя передавать
управление программой во внутренний блок, цикл или
оператор IF, нельзя также передавать управление из
обработчика исключительных ситуаций обратно в текущий
блок.
2.5. Циклы
Простые циклы
Синтаксис простых циклов (основных циклов языка)
таков:
LOOP
последователъностъ_операторов;
END LOOP;
32
От бесконечного выполнения цикла нас предохранит
оператор EXIT WHEN, обеспечивающий его завершение,
имеющий следующий синтаксис:
EXIT [WHEN условие]
Например:
LOOP
EXIT WHEN ranking_level > max_rank
set_rank (ranking_level);
ranking_level := ranking_level + 1;
END LOOP;
Цикл WHILE
Синтаксис цикла
продолжения) таков:
WHILE
(цикл
с
условием
WHILE условие
LOOP
последователъностъ_ операторов;
END LOOP;
Проверка условия происходит перед каждой итерацией
(шагом) цикла. Если условие истинно, выполняется
последовательность операторов. Если же проверка условия
дает ложное или NULL-значение, цикл завершается и
управление программой передается оператору, следующему
за оператором END LOOP:
WHILE ranking_level <= max_rank
LOOP
set_rank (ranking_level);
ranking_level := ranking_level + 1;
END LOOP;
33
Числовые циклы FOR
Число итераций в простых циклах и циклах WHILE не
известно заранее – оно зависит от условий, заданных в
циклах. В числовых же циклах FOR число итераций заранее
определено. Синтаксис цикла FOR таков:
FOR счетчик_цикла IN [REVERSE] нижняя_граница..
верхняя_граница
LOОР
последовательность_ операторов;
END LOOP;
где счетчик_цикла – неявно создаваемая индексная переменная,
нижняя_граница и верхняя_граница указывают
число итераций,
а последовательность_операторов – это содержимое цикла.
Границы цикла вычисляются один раз и определяют
общее число итераций, проходимых счетчиком цикла от
нижней границы до верхней границы. При этом счетчик
каждый раз увеличивается на 1 (либо уменьшается на 1 – в
случае наличия ключевого слова REVERSE) до тех пор, пока
цикл не завершится.
Например:
FOR ranking_level IN 1 .. max_rank
LOOP
set_rank (ranking_level);
END LOOP;
34
3. DML в PL/SQL
Допустимыми операторами DML являются SELECT
(выбрать), INSERT (вставить), UPDATE (обновить) и
DELETE (удалить). В программе PL/SQL можно
использовать любой из этих операторов SQL. Каждый
оператор действует в соответствии со своим названием: с
помощью SELECT в таблице выбираются строки, указанные
в условии WHERE; посредством INSERT к таблице базы
данных добавляются строки; с помощью UPDATE
модифицируются строки, указанные в условии WHERE; с
помощью DELETE эти строки удаляются. Помимо условия
WHERE, в этих операторах могут применяться и другие
конструкции.
Каким
образом
программы
должны
полчать
необходимые для своей работы данные? Их можно загрузить
из базы данных. Для этого можно использовть оператор SQL:
Select count(*) into v_emp_count from emp;
Видно, что данный оператор похож на стандартный
оператор select, однако содержит ключевое слово into,
которое ранее в подобных конструкциях не встречалось.
Именно с помощью этого ключевого слова результат запроса
select записывается в переменную. Можно получить из базы
данных не одно, а несколько значений.
3.1 Курсоры
Когда в последнем примере использовался оператор
select, при этом фактически был неявно объявлен курсор.
Неявный курсор представляет собой оператор SQL, который
присутствует в теле программы и в случае SQL-оператора
35
select содержит ключевое слово into. Система берет на себя
всю заботу об управлении неявными курсорами.
Курсор (cursor) — это указатель на область памяти,
которая содержит информацию, необходимую для
завершения
обработки,
включая:
число
строк,
обрабатываемых оператором, указатель на представление
этого оператора и активный набор (active set), т.е. набор
строк, возвращаемых запросом.
Для того, чтобы сделать программу более эфективной
необходимо
объявить
курсор
явным
образом.
Использование явных курсоров необходимо для того,
чтобы Oracle имел возможность заранее подготовить SQLоператор для выполнения в программе. В результате
достигается более эфективное использование памяти.
DECLARE
students_rec students%ROWTYPE;
v_Major students.major%TYPE := 'Computer Science';
/* Объявление курсора */
CURSOR cur_Students IS select *
from students
where major = v_Major;
BEGIN
OPEN cur_Students;
LOOP
FETCH cur_Students INTO students_rec;
EXIT WHEN cur_Students%NOTFOUND;
…
END LOOP;
CLOSE cur_Students;
END;
36
С помощью оператора OPEN Oracle оповещается о
том, что мы собираемся использовать курсор. После чего
можно приступать к выборке данных из таблицы, что делает
оператор FETCH, полученные данные записываются в
переменные.
Атрибут курсора %FOUND
Атрибут
%FOUND возвращает информацию о
результате самой последней выборки из курсора. Он
возвращает TRUE, если последняя инструкция FETCH для
явного курсора вернула строку, и FALSE — в противном
случае.
Атрибут курсора %NOTFOUND
Атрибут %NOTFOUND позволяет убедиться, что
DML-инструкция не обработала ни одной строки. Его
значение противоположно значению атрибута %FOUND.
Атрибут курсора %ROWCOUNT
Атрибут %ROWCOUNT возвращает количество
строк, извлеченных из курсора на момент обращения к этому
атрибуту. Сразу после открытия курсора атрибут возвращает
нуль. После выборки очередной строки значение атрибута %
ROWCOUNT увеличивается на 1.
Атрибут курсора %ISOPEN
Атрибут %ISOPEN возвращает значение TRUE, если
курсор открыт, и значение FALSE в противном случае.
37
3.2 Курсоры с параметрами
Параметры – это средство передачи информации в
программный модуль и из него. При правильном
использовании они делают модули более полезными и
гибкими. PL/SQL позволяет передавать параметры курсорам.
Они выполняют те же функции, что и параметры программных модулей, а также несколько дополнительных.
• Расширение
возможности
многократного
использования курсоров. Вместо того чтобы жестко
кодировать в предложении WHERE значения,
определяющие условие отбора данных, можно
использовать параметры для передачи в это
предложение нового набора значений при каждом
открытии курсора.
• Решение проблем, связанных с областью действия
курсоров. Если вместо жестко закодированных
значений в запросе используются параметры,
результирующий набор строк курсора не привязан к
конкретной переменной программы или блока. Если
в программе имеются вложенные блоки, курсор
можно определить на верхнем уровне и
использовать его во вложенных блоках с
объявленными в них переменными.
Количество параметров курсора не ограничено. В
операторе OPEN для каждого параметра должно быть задано
значение, за исключением параметров, для которых
определены значения по умолчанию.
Например, опишем курсор с параметрами :
DECLARE
CURSOR emp_cur (emp_id NUMBER := 0)
IS
38
SELECT employee_id, emp_name
FROM employee
WHERE employee_id = emp_id;
Перед использованием курсор надо открыть с помощью
оператора:
OPEN emp_cur (значение_параметра);
3.3
Курсорный цикл FOR
Использование курсоров совместно с циклом for
значительно расширяет их возможности. Курсорный цикл
for включает курсор select и позволяет осуществлять
выборку нескольких строк из базы данных, если таковым
должен быть результат нашего запроса. При этом написание
программы оказывается достаточно простым, и не нужно
заботиться об открытии и закрытии курсора. Oracle сделает
это самостоятельно внутри цикла. Рассмотрим пример
комбинации курсора и цикла for.
DECLARE
CURSOR cur_seminar IS
SELECT lector_ id, room_number
FROM seminar
WHERE sem_dt = SYSDATE;
BEGIN
FOR rec IN cur_seminar
LOOP
update_schedule (rec.lector_id, rec.room_number);
END LOOP;
END;
39
Объединение курсора и цикла for демонстрирует
истинную мощь PL/SQL. Отметим, что объявление
переменной курсора не содержится в разделе declare. Oracle,
обнаружив в операторе
for переменную rес, будет
использовать эту переменную для сохранения результатов
выполнения курсора.
40
4.
Обработка ошибок в PL/SQL
В языке PL/SQL ошибки всех видов интерпретируются
как исключения, то есть недопустимые ситуации, которых
всячески следует избегать. К числу исключений относятся:
•
ошибки, которые генерируются системой (в
частности такие, как нехватка памяти и
повторяющееся значение индекса);
• ошибки, вызванные действиями пользователя;
• предупреждения, выдаваемые приложением
пользователю.
PL/SQL перехватывает ошибки и реагирует на них при
помощи так называемых обработчиков исключений.
Механизм функционирования обработчиков исключений
позволяет четко отделить код обработки ошибок от
исполняемых операторов, дает возможность реализовать
обработку ошибок, управляемую событиями, отказавшись от
устаревшей линейной модели программирования. И
независимо от того, как и по какой причине было
инициировано конкретное исключение, оно обрабатывается
одним и тем же обработчиком в разделе исключений.
Когда происходит ошибка, будь то системная ошибка
или ошибка в приложении, в PL/SQL инициируется
исключение. В результате выполнение исполняемого блока
прерывается и управление передается отдельному разделу
исключений в текущем блоке, если таковой имеется. После
обработки исключения возврат в тот блок, из которого оно
было инициировано, не возможен, поэтому управление
переходит во внешний блок.
Механизм обработки исключений в PL/SQL достаточно
мощен и гибок, но его эффективное использование требует
определенных
навыков.
Очень
важно
определить
41
собственную стратегию и последовательность обработки
ошибок еще до начала работы над программным кодом.
В таблице 8 представлены стандартные исключения в
РL/SQL.
Имя исключения
Описание
CURSOR_ALREADY_OPEN
Попытка открыть (OPEN) курсор,
который был открыт ранее.
Поэтому
перед
повторным
открытием курсор необходимо
сначала закрыть (CLOSE)
Ссылка на несуществующий курсор.
Обычно это происходит при попытке
извлечь
данные
(FETCH)
из
неоткрытого курсора или закрыть
(CLOSE) курсор до его открытия
(OPEN)
PL/SQL выполняет SQL-инструкцию,
которая
не
может
успешно
преобразовать символьную строку в
число. Это исключение отличается от
исключения VALUE_ERROR, инициируемого только
SQL-инструкцией
Попытка программы подключиться к
СУБД Oracle с неверным именем
пользователя и паролем
Это исключение инициируется в трех
случаях: при выполнении инструкции
SELECT INTO (неявный курсор),
которая не возвращает ни одной
строки; при наличии ссылки на неинициализированную строку локальной таблицы PL/SQL; при попытке
выполнить операцию чтения после
достижения конца файл с использованием пакета UTL_FILE
Прогамма пытается обратиться к базе
данных (обычно посредством ин-
INVALID_CURSOR
INVAUD_NUMBER
LOGIN_DENIED
NO_DATA_FOUND
NOT_LOGGED_ON
42
PROGRAM_ERROR
TOO_MANY ROWS
VALUE_ERROR
ZERO_DIVIDE
струкции DML) до подключения к
СУБД Oracle
Внутренняя программная ошибка
PL/SQL. В сообщении об ошибке
обычно предлагается обратиться в
службу поддержки Oracle
Инструкция SELECT INTO возвращает несколько строк, хотя может
возвращать лишь одну строку; если
же их больше одной, можно
поместить инструкцию SELECT в
явное
определение
курсора
и
выбирать (FETCH) строки из него по
одной
Ошибка, связанная с преобразованием, усечением или проверкой
ограничений
числовых
или
символьных данных, Это общее и
очень распространенное исключение.
Если подобная ошибка содержится а
инструкции SQL или DML, то в
блоке
PL/SQL
инициируется
исключение INVAUD_NUMBER
Попытка выполнить в программе
деление числа на ноль
Для того чтобы обработать или перехватить
исключение, нужно написать для него обработчик.
Обработчики исключений располагаются после исполняемой
части блока, но перед завершающим его ключевым словом
END. Начало блока исключений отмечает ключевое слово
EXCEPTION:
DECLARE
... объявления .. .
BEGIN
... исполняемые операторы . ..
43
[ EXCEPTION
... обработчики исключений ...]
END;
Например:
DECLARE
comp_id NUMBER:=35;
BEGIN
…
DELETE FROM company WHERE company_id = comp_id;
EXCEPTION
WHEN no_data_found THEN
raise_application_error(-20001,' Неправильный
идентификатор компании');
END;
Встроенная функция raise_application_error используется
для генерации исключения в нашей программе.
44
5. Хранимые процедуры и
функции
5.1. Процедуры
Процедура — это модуль, который осуществляет одно
или несколько действий. Поскольку вызов процедуры в
PL/SQL является отдельным исполняемым оператором, блок
кода PL/SQL может состоять только из вызова процедуры.
Процедуры относятся к числу ключевых компонентов
модульного
кода,
позволяющих
разработчикам
оптимизировать код и повторно использовать его. Процедура
PL/SQL имеет следующую структуру:
PROCEDURE имя [(параметр, [параметр ...])]
IS
[объявления]
BEGIN
исполняемые операторы
[EXCEPTION
обработчики исключений]
END [имя];
• имя — имя процедуры. Следует сразу же за
ключевым словом PROCEDURE.
•
•
параметр — необязательный список параметров,
которые применяются для передачи данных в
процедуру и возврата информации из процедуры в
вызывающую программу.
объявления - объявления локальных идентификаторов
для этой процедуры. При отсутствии таковых между
45
•
•
ключевыми словами IS и BEGIN не будет никаникаких выражений.
испопняемые операторы — операторы, которые
выполняются процедурой при вызове. Между
ключевыми словами BEGIN и END или EXCEPTION
должен находиться, по крайней мере, один
исполняемый оператор.
обработчики
исключений
—
обработчики
исключений
для
процедуры.
Не
являются
обязательными. Если в процедуре не обрабатываются
никакие исключения,слово EXCEPTION можно
опустить и завершить исполняемый раздел ключевым
словом END.
Например:
CREATE OR REPLACE PROCEDURE AddNewStudent (
v_FirstName in students.first_name%TYPE,
v_LastName in students.last_name%TYPE,
v_Major
in students.major%TYPE) IS
BEGIN
INSERT INTO students (ID, first_name, last_name, major,
current_credits)
VALUES (student_sequence.nextval, v_FirstName,
v_LastName, v_Major, 0);
COMMIT;
END AddNewStudent;
5.2. Функции
Функция — это модуль, который возвращает значение.
В отличие от вызова процедуры, представляющего собой
46
отдельный оператор, вызов функции всегда является частью
оператора, то есть он включается в выражение или служит в
качестве
значения
по умолчанию, присваиваемого
переменной при объявлении.
Возвращаемое функцией значение принадлежит к
определенному типу данных. Функция может использоваться
вместо выражения, которое имеет тот же тип данных, что и
возвращаемое ею значение. Функции играют особенно
важную роль в обеспечении модульного подхода. К примеру,
реализация отдельного бизнес-правила или формулы в
приложении должна помещаться в функцию. Любой запрос,
возвращающий одну строку, также должен объявляться
внутри функции, для того чтобы его можно было
использовать повторно.
Функция имеет почти такую же структуру, как и
процедура, за исключением того, что предназначение
ключевого слова RETURN в ней совсем иное. Структура
функции такова:
FUNCTION имя [(параметр [, параметр ...])]
RETURN тип возвращаемых данных
IS
[объявления]
BEGIN
исполняемые операторы
[EXCEPTION
обработчики исключений]
END [имя];
•
Назначение каждого элемента структуры описано ниже.
имя — имя процедуры. Следует сразу же за ключевым
словом FUNCTION.
47
•
•
•
•
•
параметр — необязательный список параметров,
которые применяются для передачи данных функции и
возврата информации из нее в вызывающую
программу.
тип_возвращаемых_данных — тип возвращаемого
функцией значения. Это обязательная часть заголовка
функции (описывается более детально в следующих
разделах).
объявления — объявления локальных идентификаторов
для указанной функции. Если таких идентификаторов
нет, между ключевыми словами IS и BEGIN не будет
никаких выражений.
исполняемые операторы — операторы, которые
выполняются
функцией
при
вызове.
Между
ключевыми словами BEGIN и END или EXCEPTION
должен находиться, по крайней мере, один
исполняемый оператор.
обработчики исключений — обработчики исключений
для процедуры (не являются обязательными). Если в
процедуре не обрабатываются никакие исключения,
слово EXCEPTION можно опустить и завершить
исполняемый раздел ключевым словом END.
CREATE OR REPLACE FUNCTION tot_sales (
comp_id IN company.company_id%TYPE,
status IN order.status%TYPE := NULL)
RETURN NUMBER
IS
CURSOR sales_cur IS
SELECT SUM (amount*discount)
FROM item
WHERE EXISTS (SELECT * FROM order
48
WHERE order.order_id = item.order_id
AND company_id = comp_id
AND status_code LIKE status);
ret_val NUMBER;
BEGIN
OPEN sales_cur;
FETCH sales_cur INTO ret_val;
IF sales_cur%NOTFOUND THEN
RETURN NULL;
ELSE
RETURN ret_val;
END IF;
CLOSE sales_cur;
END tot_sales;
Очень важно понимать различие между формальными и
фактическими параметрами. Формальные параметры
представляют собой имена, объявленные в списке
параметров заголовка модуля, тогда как фактические — это
значения или выражения, которые помещаются в список
параметров при вызове модуля. Рассмотрим функцию
tot_sales, заголовок которой выглядит следующим образом:
FUNCTION tot_sales (
comp_id IN company.company_id%TYPE,
status IN order.status%TYPE := NULL)
RETURN number;
Формальными здесь являются: comp_id — первичный
ключ таблицы company, а также status — параметр,
определяющий состояние заказов, которые должны быть
49
включены в расчет объема продаж. Данные параметры вне
функции не существуют, их можно считать «заполнителями»
для фактических значений, передаваемых функции при
использовании ее в программе. Когда функция tot_sales
вызывается в коде, на место формальных параметров
помещаются фактические, то есть переменные, значения
которых будут переданы данной функции.
new_sales := tot_sales (comp_id, 'N');
Вызов функции может производиться из любого места
исполняемого
оператора
PL/SQL,
где
допускается
использование выражения.
50
6. Пакеты
Пакет представляет собой сгруппированный по
определенным правилам набор элементов кода PL/SQL. Он
обеспечивает логическую структуру, предназначенную для
организации программ, курсоров, типов данных и
переменных. Значимость пакетов объясняется тем, что они
позволяют скрывать логику и данные, а также определять
глобальные данные, существующие в течение сеанса.
Пакеты — очень важная составная часть языка PL/SQL,
без использования которой невозможно создать сложный
прикладной проект. Чтобы это понять, рассмотрим, какие
преимущества обеспечивают пакеты.
• Упрощают
сопровождение
и
расширение
приложений. При увеличении объема кода качество
приложений определяется тем, насколько легко их
сопровождать. С этой точки зрения пакеты играют
исключительна
важную
роль,
поскольку
обеспечивают инкапсуляцию кода (в частности, они
позволяют скрыть SQL-инструкции за интерфейсом
процедур), дают возможность определить константы
и сгруппировать логически связанные функции. В
результате
приложение
становится
более
структурированным и надежным.
• Повышают производительность приложений. Во
многих ситуациях использование пакетов позволяет
повысить производительность и эффективность
работы
приложений.
Определив
постоянные
структуры данных уровня пакета, можно кэшировать
статические значения из базы данных. Это дает
возможность избежать повторных запросов и,
51
следовательно, значительно ускорить получение
результата. Кроме того, подсистема управления
памятью Oracle оптимизирована для доступа к
откомпилированному коду пакетов.
• Поддержка приложений и исправление недостатков
встроенных элементов. Некоторые из существующих
программных компонентов Oracle имеют определенные недостатки, в частности не лучшим образом
реализованы важнейшие функции встроенных
пакетов (напр. DBMS_OUTPUT). Мириться с этим
обязательно,
можно
разработать
совсем
не
собственный пакет, устранить значительную часть
недостатков и использовать его вместо стандартного.
Подобного результата можно достичь и с помощью
отдельных функций и процедур, но использование
пакетов является более предпочтительным подходом.
Пакет состоит из двух частей — спецификации и тела.
Спецификация является обязательной частью и определяет,
как разработчик может использовать пакет: какие программы
можно вызывать, какие курсоры открывать и т. д. Тело
пакета — это необязательная, но почти всегда
присутствующая часть, она содержит код перечисленных в
спецификации программ (и, возможно, курсоров), а также
другие необходимые элементы кода.
CREATE OR REPLACE PACKAGE employee_pkg
AS
max_salary NUMBER;
SUBTYPE fullname IS VARCHAR2 (100);
FUNCTION full_name (
l employee.last_name%TYPE,
f employee.first_name%TYPE)
52
RETURN fullname;
FUNCTION full_name ( v_employee_id IN
employее.employee_id%TYPE)
RETURN fullname;
END employee_pkg;
Обратите внимание, что в пакете объявляется вторая
функция с именем full_name. Она принимает первичный
ключ таблицы сотрудников и возвращает полное имя
сосотрудника. Это типичный пример перегрузки.
Теперь рассмотрим, что собой представляет тело
пакета:
CREATE OR REPLACE PACKAGE BODY employee_pkg
AS
FUNCTION full_name (l employee.last_name%TYPE,
f employee.first_name%TYPE)
RETURN fullname
IS
BEGIN
RETURN l || ’.’ || f;
END;
FUNCTION full_name (
vemployee_id IN employee.employee_id%TYPE)
RETURN fullname
IS
ret_val fullname;
BEGIN
SELECT fullname (last_name, first_name) INTO ret_val
FROM employee;
WHERE employee_id = vemployee_id;
RETURN ret_val;
53
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN NULL;
WHEN TOO_MANY_ROWS THEN errpkg.recnstop;
END;
END employee_pkg;
Поясним некоторые, связанные с пакетами понятия и
концепции.
• Сокрытие
информации.
Выполняя
сокрытие
информации о системе или приложении, обычно
преследуют две цели. Во-первых, освободить
пользователя
(разработчика
приложения)
от
необходимости вникать в ненужные детали и помочь
ему сконцентрироваться на важном. Во-вторых,
воспрепятствовать доступу к конфиденциальной
информации. Например, формула, вычисляющая
некоторое значение, может быть не важна для
разработчика, а может быть и секретна. В обоих
случаях имеет смысл предоставить ему интерфейс для
вызова функции, вычисляющей это значение.
• Общие и личные элементы. Концепция общих и
личных элементов тесно связана с концепцией
сокрытия информации. Общий код определяется в
спецификации пакета и доступен любой схеме,
имеющей на этот пакет привилегию EXECUTE.
Личный код определяется и видим только внутри
пакета. Внешние программы, использующие пакет, не
могут видеть или вызывать личный код. Приступая к
разработке пакета, нужно решить, какие из его
элементов будут общими, а какие — личными. Кроме
того, тело пакета можно скрыть от других
схем/разработчиков. В таком случае пакет применяется
для сокрытия деталей реализации программ. Это
54
•
особенно важно, если требуется изолировать
переменные компоненты приложения, такие как
фрагменты кода, зависящие от платформы, часто
меняющиеся структуры данных и временные решения.
Спецификация пакета. Она содержит определения всех
общедоступных элементов пакета, на которые можно
ссылаться извне. Спецификация похожа на большой
раздел объявлений, она не содержит блоков PL/SQL
или исполняемого кода. Если спецификация хорошо
спроектирована, разработчик может узнать из нее всю
требуемую для использования пакета информацию.
При
этом никогда не возникнет необходимость
заглянуть «за интерфейс», то есть в тело пакета,
содержащее реализацию его компонентов.
55
Литература
1. Коннор МакДональд, Хаим Кац, Кристофер
Бек, Джоел Кальман, Дэвид Нокс. «Oracle
PL/SQL для профессионалов: практические
решения» Москва • Санкт-Петербург • Киев,
2005.
2. Том Кайт. “Oracle для профессионалов”.
Москва • Санкт-Петербург • Киев, Торговоиздательский дом DiaSoft, 2003.
3. Rick Greenwald, Robert Stackowiak, Jonathan
Stern.“Oracle Essentials: Oracle Database 10g”,
3rd Edition, O'Reilly, 368, 2004.
56
ТЕКСТ ВОСПРОИЗВОДИТСЯ В ТОМ ВИДЕ,
В КОТОРОМ ПРЕДСТАВЛЕН АВТОРОМ
Сдано в производство
01.05.2009 г. Подписано в печать
19.05.2009 г. Формат бумаги 60X84 1/16. Усл. печ. л. 3,5. Тираж
100 экз.
Издательский дом "Технический университет", Тбилиси,
Ул. М. Костава, 77
Download