Программирование на PLSQL. Учебно-методическое пособие по дисциплине Базы данных
.pdf
При использовании атрибута %ROWCOUNT необходимо добавлять проверку на отсутствие строк с помощью атрибута %NOTFOUND, так как, если команда FETCH не возвращает строк, счетчик %ROWCOUNT не увеличивается.
Курсоры с параметрами
Параметры позволяют передать значения курсору в момент его открытия и используются при выполнении запроса. Явный курсор можно открывать многократно с разными активными наборами данных.
Типы данных параметров такие же, как для скалярных переменных, но не задаются их размеры. Имена параметров позволяют ссылаться на них в выражениях запроса курсора.
Синтаксис
CURSOR имя_курсора [(имя_параметра тип данных,...)]
IS
предложение select; |
|
|
где: |
|
|
имя_курсора |
идентификатор описанного курсора. |
|
имя_параметра |
имя параметра. |
|
тип данных |
скалярный тип данных параметра. |
|
предложение select |
команда SELECT без предложения INTO. |
|
Когда курсор открывается, значение каждого параметра передается в соответствии с его местом в списке.
Управление транзакциями
Управлять логикой транзакций можно с помощью команд COMMIT и ROLLBACK языка SQL, делая постоянными одни изменения в базе данных и отменяя другие. Транзакции DML начинаются с первой команды после COMMIT или ROLLBACK и завершаются следующим успешным выполнением COMMIT или ROLLBACK.
11
УПРАВЛЕНИЕ ПОТОКОМ ДАННЫХ В БЛОКАХ PL/SQL
Оператор IF
Оператор IF PL/SQL позволяет выборочно выполнять действия в зависимости от некоторых условий.
Синтаксис
IF условие THEN операторы1;
[ELSIF условие THEN
операторы2;]
[ELSE]
операторы3;]
END IF;
логическая переменная или выражение (результат — "истинно", "ложно" или "не определено").
Количество предложений ELSIF не ограничено.
Предложение ELSE может быть только одно.
Null в выражениях и операциях сравнения
Любое выражение, содержащее неопределенное значение, дает результат NULL, за исключением выражений, образованных путем конкатенации (||), где неопределенное значение рассматривается как пустая строка.
Любое простое сравнение, содержащее неопределенное значение, дает результат NULL.
Сравнение IS NULL дает результат TRUE или FALSE.
Логическое выражение может состоять из простых логических условий и логических операторов AND, OR и NOT.
Циклы
PL/SQL предлагает несколько путей организации циклов для повторного выполнения предложений.
Простой цикл LOOP
Простой цикл — это группа повторно выполняемых операторов.
Синтаксис
LOOP
оператор1; оператор2;
………
12
EXIT [WHEN условие];
END LOOP;
где:
условие логическая переменная или выражение (результат которого - TRUE, FALSE или NULL).
Цикл WHILE
Цикл WHILE используется для повторения последовательности операторов в течение всего времени, пока выполняется заданное условие, т. е. пока значение условия равно TRUE ("верно"). Условие вычисляется в начале каждой итерации. Как только значение условия становится FALSE ("неверно"), выполнение цикла прекращается. Если условие равно FALSE в начале цикла, последовательность операторов больше не выполняется.
Синтаксис
WHILE условие LOOP
оператор1; оператор2;
…
END LOOP;
где:
условие логическая переменная или выражение (результат которого - TRUE, FALSE или NULL).
Цикл FOR
Синтаксис
FOR индекс IN [REVERSE]
нижняя_граница . . верхняя_граница LOOP оператор1; оператор2;
…
END LOOP;
где: индекс
REVERSE
нижняя_граница верхняя_граница
Ссылаться на индекс можно только внутри цикла; вне цикла он не определен.
Ссылаться на текущее значение индекса можно в выражении.
Нельзя ссылаться на индекс в качестве переменной в левой части оператора присваивания.
Циклы FOR с курсорами
Циклы FOR с курсорами обрабатывают строки в явном курсоре. Это — сокращенная форма записи, поскольку происходит открытие курсора, выборка строк по одной за каждое прохождение цикла и автоматическое закрытие курсора после того, как все строки обработаны. Выход из цикла производится автоматически в конце прохождения цикла, во время которого была выбрана последняя строка.
Синтаксис
FOR имя_записи IN имя_курсора LOOP оператор1; оператор2;
……
END LOOP;
где:
имя_записи имя неявно описанной записи. имя_курсора идентификатор для ранее описанного курсора.
Использование предложения FOR UPDATE
При работе с командами обновления и удаления существует возможность блокировки записей. Для этого включите в запрос, выполняемый в курсоре, предложение FOR UPDATE. При открытии курсора это предложение блокирует соответствующие строки. Поскольку в конце транзакции сервер Oracle снимает всю блокировку, не нужно фиксировать изменения между выборками из явного курсора, если используется предложение FOR UPDATE.
Синтаксис
SELECT... FROM... FOR UPDATE [OF column reference] [NOWAIT];
где:
column reference столбец таблицы, к которому обращен запрос; NOWAIT возвращает ошибку Oracle, если строки
заблокированы другим сеансом.
14
Запрашивая несколько таблиц, можно ограничить блокировку строк конкретными таблицами с помощью предложения FOR UPDATE. Строки таблицы блокируются только в случае, если предложение FOR UPDATE содержит ссылку на столбец этой таблицы.
Предложение WHERE CURRENT OF
Можно использовать команду DELETE или UPDATE с предложением WHERE CURRENT OF имя_курсора для ссылки на последнюю строку, выбранную командой FETCH. Если используется это предложение, курсор, на который делается ссылка, должен существовать и содержать в запросе предложение FOR UPDATE. В противном случае возникнет ошибка. Это предложение позволяет производить обновления и удаления в текущей строке без явной ссылки на псевдостолбец ROWID.
ОБРАБОТКА ОШИБОК
Исключение — это переменная в PL/SQL, возбуждаемая во время выполнения блока и прекращающая выполнение действий в теле блока. Если PL/SQL возбуждает исключение, выполнение блока прерывается всегда, но можно указать обработчик исключения, который выполнит некоторые заключительные действия.
Методы возбуждения исключения
•Исключение возбуждается автоматически сервером Oracle в случае возникновения ошибки Oracle. Например, в результате запроса из базы данных не выбрано ни одной строки, возникает ошибка ORA-01403, и PL/SQL возбуждает исключение NO_DATA_FOUND.
•Исключение возбуждается явно, выполняя предложение RAISE внутри блока. Возбуждаемое исключение может быть как предопределенным, так и пользовательским.
•Перехват исключения обрабатывается в секции обработки исключений (секции EXCEPTION). При успешной обработке исключение не распространяется во внешний блок или среду.
•Если исключение возбуждено в выполняемой секции блока, а соответствующего обработчика исключений нет, выполнение блока PL/SQL прекращается в аварийном порядке.
15
Типы исключений Существует три типа исключений.
Исключение |
Описание |
Указание |
|
|
|
Предопределенное, |
Одна из примерно 20 |
Описание не требуется. |
возбуждаемое |
типичных ошибок, |
Позвольте серверу |
сервером |
возникающих при |
Oracle возбуждать такие |
|
выполнении программ |
исключения неявно |
|
на PL/SQL |
|
Непредопределенное |
Любая другая |
Требуется описание в |
возбуждаемое |
стандартная ошибка |
декларативной секции, |
сервером |
сервера |
после чего сервер Oracle |
|
|
возбуждает такие |
|
|
исключения неявно |
Пользовательское |
Условие, которое |
Необходимо определять |
возбуждение |
разработчик считает |
в декларативной секции и |
|
ошибочным |
возбуждать исключения |
|
|
явно |
Перехват предопределенных исключений
Перехват любого исключения осуществляется путем включения соответствующей подпрограммы в секцию обработки исключений блока
PL/SQL.
Синтаксис
EXCEPTION
WHEN имя_исключения1 [OR имя_исключения2..] THEN оператор1; оператор2;
…
WHEN имя_исключения3 [OR имя_исключения4..] THEN оператор1; оператор2;
…
WHEN OTHERS THEN
оператор1; оператор2;
...]
где:
имя_исключения стандартное имя предопределенного исключения или имя пользовательского исключения, описанного в декларативной секции;
WHEN OTHERS указывает программу обработки для всех исключений, не перечисленных явно.
16
Предложение WHEN OTHERS помещается после всех остальных обработчиков исключений. Предложение WHEN OTHERS может быть только одно.
Примеры предопределенных исключений
Имя исключения |
Ошибка Oracle |
Описание |
|
||
|
|
|
|
||
NO_DATA_FOUND |
ORA-01403 |
Команда SELECT не |
|
||
|
|
вернула |
ни |
одной |
|
|
|
строки данных |
|
|
|
|
|
|
|
|
|
TOO_MANY_ROWS |
ORA-01422 |
Команда |
|
SELECT |
|
|
|
вернула |
более |
одной |
|
|
|
строки |
|
|
|
|
|
|
|||
INVALID_CURSOR |
ORA-01001 |
Недопустимая операция |
|||
|
|
с курсором |
|
|
|
|
|
|
|
|
|
ZERO_DIVIDE |
ORA-01476 |
Попытка |
деления |
на |
|
|
|
ноль |
|
|
|
|
|
|
|
|
|
DUP_VAL_ON_INDEX |
ORA-00001 |
Попытка |
|
вставки |
|
|
|
дубликата |
значения |
в |
|
|
|
столбец, |
для которого |
||
|
|
имеется |
уникальный |
||
|
|
индекс |
|
|
|
|
|
|
|
|
|
INVALID_NUMBER |
ORA-01722 |
Неудачное |
|
|
|
|
|
преобразование |
строки |
||
|
|
в число |
|
|
|
|
|
|
|
|
|
В один блок можно включить несколько обработчиков исключений, каждый из которых выполняет собственный набор действий.
Если возникает исключение, PL/SQL перед выходом из блока выполняет только один обработчик.
Пример.
Удалить непопулярные фильмы
17
18
Перехват непредопределенных исключений
Если вы не хотите использовать обработчик WHEN OTHERS, то для перехвата неопределенных ошибок сервера Oracle необходимо сначала их объявить. После этого объявленное исключение будет возбуждаться неявно. Необходимо сослаться на объявленное исключение в секции обработки исключений.
1. Объявление имя исключения в декларативной секции.
Синтаксис |
|
имя_исключения |
EXCEPTION; |
где: |
|
имя_исключения |
имя данное исключению. |
2.Привязка объявленного исключения со стандартным номером ошибки сервера.
Синтаксис
PRAGMA EXCEPTION_INIT(имя_исключения,номер_ошибки);
где: |
|
имя_исключения |
ранее описанное исключение; |
номер ошибки |
стандартный номер ошибки сервера Oracle. |
3.Ссылка на объявленное исключение в программе в секции обработки исключений.
Перехват пользовательских исключений
Для перехвата пользовательского исключения необходимо сначала объявить его, а затем возбудить явно.
1.Объявление имени пользовательского исключения в декларативной секции.
Синтаксис
имя_исключение EXCEPTION;
где: |
|
имя_исключения |
имя, данное исключению. |
2.Возбуждение исключения явно в исполняемой секции с помощью предложения RAISE.
Синтаксис
RAISE имя_исключения;
где: |
|
имя_исключения |
имя, данное исключению. |
3.Ссылка на объявленное исключение в программе в секции обработки исключений.
19
Функции для перехвата ошибок
Если возбуждается исключение, то его код и связанное с ним сообщение можно определить с помощью двух функций. Имея код или сообщения, можно решить, какие действия предпринимать.
|
Функция |
|
|
Описание |
|
|
|
|
|
|
|
|
|
SQLCODE |
|
Возвращает числовое значение кода ошибки |
|
|||
|
|
|
|
|
|
|
SQLERRM |
|
Возвращает |
сообщение с длиной не более 71 символа, |
|
||
|
|
|
связанное с кодом ошибки, если SQLCODE<0 |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
Примеры значений SQLCODE |
|
|
|
|
|
|
||
|
Значение SQLCODE |
|
Описание |
|
||
|
|
|
|
|
|
|
|
|
0 |
|
Исключений не было |
|
|
|
|
|
|
|
|
|
|
|
4 |
|
Пользовательское исключение |
|
|
|
|
|
|
|
|
|
|
|
+ 100 |
|
Исключение NO_DATA_FOUND |
|
|
|
|
|
|
|
||
|
Отрицательное число |
|
Номер другой ошибки сервера Oracle |
|
||
|
|
|
|
|
|
|
Процедура RAISE_APPLICATION_ERROR
Процедура позволяет посылать собственные пользовательские сообщения об исключениях из хранимых программ.
Синтаксис
RAISE_APPLICATION_ERROR(номер_ошибки, сообщение[, TRUE|FALSE]);
где:
номер_ошибки номер исключения в диапазоне от -20000 до -20999; сообщение текст сообщения об исключении, заданное пользователем до 2048 байтов.
TRUE|FALSE логический параметр
(TRUE - исключение необходимо поместить в список предыдущих ошибок, FALSE - исключение должно заместить все предыдущие).
20
