Чтение онлайн

на главную - закладки

Жанры

Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ

Борри Хелен

Шрифт:

END

Повторный вызов исключения

Предположим, вам нужно перехватить и внести во внешнюю таблицу протокола непредвиденную ошибку, перед тем как позволить исключению выполнить свою работу и завершить процедуру или триггер. Начиная с версии 1.5, можно повторно вызвать исключение - вы можете выполнить некоторую обработку исключения и завершить обработчик оператором EXCEPTION для возбуждения исключения и передачи управления на конечный END. Выполнение останавливается, и управление передается клиенту с кодом или именем исключения и подходящим сообщением в

массиве состояния ошибки.

В вашем обработчике вы выбираете SQLCODE или GDSCODE и некоторые другие контекстные переменные, записываете запись в протокол, а затем заново вызываете исключение:

BEGIN

. . .

WHEN ANY DO

BEGIN

EXECUTE PROCEDURE P_ANY_EXCEPTION (SQLCODE, другие входные данные ...);

EXCEPTION; END

END ^

Исключения в триггерах

Пользовательские исключения в триггерах способны поддерживать бизнес-правила. В примере базы данных EMPLOYEE есть правило, по которому покупатели, которым отказано в доверии, отмечаются в столбце ON_HOLD, который ограничен значениями NULL или "*". Когда добавляется запись в SALES или изменяется существующая запись с неотправленным товаром для такого покупателя, то такой заказ отклоняется, если флаг ON_HOLD не имеет значения NULL. Другое правило гласит, что заказ, который уже был отправлен, не может изменяться.

При добавлении или изменении записей заказов мы можем написать триггеры BEFORE, которые при нарушении этих правил выдают исключения и блокируют операцию.

Для любой версии Firebird мы можем написать два триггера для осуществления этих правил: BEFORE INSERT и BEFORE UPDATE.

Создадим исключения для двух условий:

CREATE EXECPTION E_CANT_ACCEPT

'Operation refused. REASON: Customer is on hold.' ^

/* Операция отклоняется. Причина: деятельность покупателя приостановлена */

CREATE EXCEPTION E_CANT_EXTEND

'Operation refused. REASON: Order already shipped.' ^

/* Операция отклоняется. Причина: заказ уже отправлен */

COMMIT ^

Триггеры для версии 1.0.x:

CREATE TRIGGER BI_SALES0 FOR SALES

ACTIVE BEFORE INSERT POSITION 0 AS

BEGIN

IF (EXISTS (SELECT 1 FROM CUSTOMER

WHERE CUST_NO = NEW.CUST_NO

AND ON_HOLD IS NOT NULL)) THEN

EXCEPTION E_CANT_ACCEPT;

END ^

/* */

CREATE TRIGGER BU_SALES0 FOR SALES

ACTIVE BEFORE UPDATE POSITION 0 AS

BEGIN

IF (OLD.ORDER_STATOS = 'shipped') THEN

EXCEPTION E_CANT_EXTEND; ELSE

IF (EXISTS (SELECT 1 FROM CUSTOMER

WHERE CUST_NO = NEW.CUST_NO

AND ON_HOLD IS NOT NULL) ) THEN

EXCEPTION E_CANT_ACCEPT;

END ^

Сообщения исключений во время выполнения

Некоторые улучшения версии 1.5 по обработке сообщений исключений обеспечивают больше возможностей написания обработчиков исключений. Статическое сообщение исключения, определенное в CREATE EXCEPTION, во время выполнения может быть заменено на другой текст, обеспечивающий лучший контекст для пользователя,

более точно идентифицирующий проблемные данные.

В следующем примере мы используем возможности версии 1.5 по реализации тех же самых правил, что и в двух триггерах предыдущего примера. На этот раз мы поместим эти правила в один триггер и используем сообщения времени выполнения.

Вот исключение:

CREATE EXCEPTION E_REFUSE_ORDER 'Operation refused. ' ^

/* Операция отвергнута */

А вот триггер:

CREATE TRIGGER BA_SALES0 FOR SALES

ACTIVE BEFORE INSERT OR UPDATE POSITION 0 AS

DECLARE VARIABLE ORDER_STATE SMALLINT = 0;

BEGIN

IF (UPDATING AND OLD.ORDER_STATUS = 'shipped') THEN

ORDER_STATE = 1;

IF (

(EXISTS (SELECT ON_HOLD FROM CUSTOMER

WHERE CUST_NO = NEW.CUST_NO

AND ON_HOLD IS NOT NULL)

AND (INSERTING OR ORDER_STATE = 0)) THEN

ORDER_STATE = 2;

IF (ORDER_STATE = 1) THEN

EXCEPTION E_REFUSE_ORDER 'Order ' || NEW.PO_NUMBER || ' already shipped.';

/* EXCEPTION E_REFUSE_ORDER 'Заказ ' || NEW.PO_NUMBER || ' уже отправлен' */

ELSE

IF (ORDER_STATE = 2) THEN

EXCEPTION E_REFUSE_ORDER

'Order '|| NEW.PO_NUMBER ||'. Customer ' || NEW.CUST_NO || ' is on hold.';

/* 'Заказ '|| NEW.PO_NUMBER ||'. Покупатель ' || NEW.CUST_NO || ' заблокирован'; */

END ^

В массиве состояния ошибки клиент получит имя исключения вместе с сообщением времени выполнения.

Список кодов ошибок

Приложение 10 содержит списки внутренне определенных исключений, включая коды SQLCODE, GDSCODE, символы для GDSCODE и сообщения на английском языке, соответствующие текущему состоянию релиза Firebird 1.5.0.

При создании двоичного кода Firebird сообщения на английском языке выбираются из внутренней базы данных. Коды SQLCODE сохраняются, но GDSCODE вычисляются на лету. Файл firebird.msg в вашем корневом каталоге Firebird создан в виде двоичного дерева, к которому обращаются клиент и сервер при работе сервера.

Написание вашего собственного списка кодов ошибок

Ради любопытства вы можете легко получить версию gbak для базы данных (с именем gbak.msg) из репозитория CVS проекта Firebird. Войдите на http:// sourceforge.net/projects/firebird и идите по ссылке CVS Browser, пока не доберетесь до ветви с именем ,/firebird/firebird2/src/msgs/. В нижней части дисплея щелкните по стрелке выпадающего списка для поиска интересующей вас ветви. Оттуда вы сможете получить файл.

Следующая хранимая процедура сгенерировала список для приложения 10. Она выводит список во внешнюю таблицу, но вы можете модифицировать эту процедуру подходящим для вас образом.

SET TERM ^;

/* Выходной файл */

CREATE TABLE ERRORCODES

EXTERNAL FILE

'С:\Program Files\Firebird\Firebird_1_5\MyData\27 94app10.txt'

(Listltem CHAR(169))^

COMMIT^

/* При необходимости уберите комментарии в следующей секции и объявите функцию ASCII_CHAR для получения символов возврата каретки и перевода строки */

Поделиться:
Популярные книги

Дракон с подарком

Суббота Светлана
3. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
6.62
рейтинг книги
Дракон с подарком

Бывшие. Война в академии магии

Берг Александра
2. Измены
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Бывшие. Война в академии магии

Мастер клинков. Начало пути

Распопов Дмитрий Викторович
1. Мастер клинков
Фантастика:
фэнтези
9.16
рейтинг книги
Мастер клинков. Начало пути

Имя нам Легион. Том 8

Дорничев Дмитрий
8. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 8

Измена. Право на счастье

Вирго Софи
1. Чем закончится измена
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на счастье

Начальник милиции 2

Дамиров Рафаэль
2. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции 2

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4

Измена. Мой заклятый дракон

Марлин Юлия
Любовные романы:
любовно-фантастические романы
7.50
рейтинг книги
Измена. Мой заклятый дракон

Предатель. Цена ошибки

Кучер Ая
Измена
Любовные романы:
современные любовные романы
5.75
рейтинг книги
Предатель. Цена ошибки

Звездная Кровь. Изгой

Елисеев Алексей Станиславович
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой

Рождение победителя

Каменистый Артем
3. Девятый
Фантастика:
фэнтези
альтернативная история
9.07
рейтинг книги
Рождение победителя

Барону наплевать на правила

Ренгач Евгений
7. Закон сильного
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Барону наплевать на правила

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь