Выбрать главу

В Классическом сервере новая версия будет доступна следующему клиенту, который соединится с базой данных.

Inactive/Active

В версии 1.5 и более поздних выполнение ALTER TRIGGER ... INACTIVE | ACTIVE обычно не приводит к ошибке "объект находится в использовании", если только существующая транзакция не заблокировала таблицу. Такое изменение не влияет на транзакции, которые уже используют эту таблицу. Причем данное изменение будет видимым следующей транзакции, которая запрашивает изменение состояния таблицы.

Удаление триггеров

В процессе проектирования базы данных и разработки приложений триггер может перестать быть полезным. Для удаления триггера соединитесь с базой данных как его владелец или пользователь SYSDBA и используйте оператор DROP TRIGGER.

Его синтаксис:

DROP TRIGGER ИМЯ;

Имя триггера должно быть именем существующего триггера. Следующий пример удаляет триггер SET_CUST_NO:

DROP TRIGGER SET CUST NO;

! ! !

ПРИМЕЧАНИЕ. Чтобы временно сделать триггер недоступным, используйте ALTER TRIGGER имя INACTIVE.

. ! .

Пора дальше

Последняя глава этой части добавляет сахарную глазурь в наш торт для разработчиков базы данных. Firebird имеет две особенности PSQL: обработка пользовательских исключений и события. С помощью исключений вы имеете весьма детальный контроль над перехватом и обработкой сотен внутренне определенных условий ошибок и множеством ваших собственных исключений. С помощью событий вы можете реализовать механизм обратных вызовов, чтобы проинформировать приложения удаленных клиентов о подтвержденных изменениях, выполненных другими клиентами.

ГЛАВА 32. Обработка ошибок и события.

В этой главе мы рассмотрим, как при выполнении модулей PSQL - триггеров и процедур - можно перехватывать и обрабатывать ошибки в выполняемом коде.

Стандартным поведением модулей PSQL при появлении исключений является остановка выполнения, отмена всей работы, выполненной с начального оператора BEGIN, переход на конечный оператор END и возврат управления клиенту с передачей одного или более сообщений об ошибке. Если этим модулем является триггер, исключение отменит работу всех предыдущих триггеров и предотвратит посылку запрашиваемых изменений DML.

Типы исключений

Может появиться три типа исключений.

* Ошибки SQL - т. е. сообщения SQL, имеющие отрицательное значение SQLCODE.

* Внутренние ошибки Firebird, которые имеют отношение к конкурирующему взаимодействию, данным, метаданным и условиям окружения. У них есть девяти- символьный код ошибки, обычно начинающийся с 3355, который уникально идентифицирует код GDSCODE. Большинство кодов GDSCODE попадают в обобщающие группы кодов SQLCODE, и при возникновении исключения вы обычно получаете и SQLCODE, и GDSCODE.

* Пользовательские исключения, которые вы объявляете как постоянные объекты базы данных и "вызываете" в коде, когда определяется специфическое условие.

Что такое исключение?

Исключение - это просто сообщение, которое генерируется, когда появляется ошибка.

Все предварительно определенные исключения - SQLCODE и GDSCODE - имеют ассоциированные с ними тексты сообщений. Сообщения по умолчанию на английском языке, но могут использоваться и другие языки. Существует небольшое количество версий сообщений на других языках (включая латинский!), другие или "находятся в работе", или "ожидают желающих поработать"[127].

В Firebird существует синтаксис DDL для создания пользовательских исключений с текстами сообщений до 78 символов. В Firebird 1.5 вы можете расширить ваши пользовательские исключения во время выполнения, заменить текст сообщения, посылаемого по сети, в зависимости от контекста.

Создание исключения

Создание исключения является одним из самых простых элементов DDL. Синтаксис:

CREATE EXCEPTION имя-исключения <сообщение>;

Имя-исключения- обычный идентификатор Firebird до 31 символа длиной. Оно должно быть уникальным среди идентификаторов исключений, а в диалекте 3 может быть заключено в кавычки. Тогда имя будет чувствительным к регистру.

<сообщение> - заключенная в апострофы строка текста в наборе символов NONE. Из-за ограничения размера текст должен быть лаконичным. Например:

CREATE EXCEPTION NO_DOGS 'NO dogs allowed!'; COMMIT;

Оператор CREATE EXCEPTION должен быть подтвержден, как и любой другой оператор DDL.

Изменение и удаление исключения

Как пользователь SYSDBA или владелец исключения, которое используется в хранимых процедурах, вы можете изменять или удалять его в любое время. Если оно используется в триггере, вы можете его только изменять и изменять только текст сообщения. Не хранится никаких зависимостей для исключений, используемых в хранимых процедурах. Это создает проблему в случае, когда вы удаляете исключение и забываете убрать его из хранимых процедур - будет неловко получить исключение по причине отсутствия исключения!

Для удаления нашего исключения NO_DOGS введите:

DROP EXCEPTION NO_DOGS;

Для его изменения:

ALTER EXCEPTION NO_DOGS 'NO dogs allowed except Irish Wolfhounds!';

! ! !

СОВЕТ. При конструировании скриптов схемы сгруппируйте вместе все ваши операторы CREATE EXCEPTION, чтобы их было проще отыскивать в процессе разработки и модификации, а также с целью документирования. Разработчики часто используют короткие префиксы или какую-нибудь систему именования исключений в соответствии с категориями пользовательских исключений.

. ! .

Исключения в действии

Внутренне определенные исключения вызываются ядром сервера в ответ на соответствующие ошибки, которые требуют прекращения выполнения. Они охватывают большое количество условий, включая каждый вид нарушения ограничений, арифметические и строковые переполнения, ссылки на отсутствующие объекты, разрушение данных и т.д. Исключения SQLCODE и GDSCODE являются теми же самыми исключениями, что и исключения, используемые при появлении ошибок в процессе выполнения операций динамического SQL. Они описаны в приложении 10.

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

У нас был в главе 30 пример, в котором пользовательское исключение применялось в триггере для прекращения события, продолжение которого нарушило бы бизнес-правило. В этом случае хранимая процедура позаботится о том, чтобы убрать зависимости из организационной структуры при удалении служащего. Это было объявлено следующим образом:

CREATE EXCEPTION REASSIGN_SALES

'Reassign the sales records before deleting this employee.' ^

/* Переназначьте записи продаж перед удалением этого служащего */

COMMIT ^

Рис. 32.1. Стандартная реакция PSQL на исключения

В том месте, где используется это исключение, процедура проверяет, является ли данный служащий участником продаж в каком-либо документе продаж. Если да, то используется пользовательское исключение для завершения процедуры. Конечно, если возникает исключение, то все другие действия, выполненные в процедуре, отменяются.

BEGIN

IE (EXISTS (SELECT PO_NUMBER FROM SALES

WHERE SALES_REP = : emporium) ) THEN

вернуться

127

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