Хелен Борри - Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
- Название:Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2006
- Город:Санкт-Петербург
- ISBN:5-94157-609-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Хелен Борри - Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ краткое содержание
Рассмотрены вопросы, необходимые разработчику для создания клиент-серверных приложений с использованием СУБД Firebird, явившейся развитием СУБД Borland Interbase 6. Содержится обзор концепций и моделей архитектуры клиент/сервер, а также практические рекомендации по работе с клиентскими библиотеками Firebird. Детально описаны особенности типов данных SQL, язык манипулирования данными (Data Manipulation Language, DML), а также синтаксис и операторы языка определения данных ( Data Definition Language, DDL). Большое внимание уделено описанию транзакций и приведены советы по их использованию при разработке приложений. Описано программирование на стороне клиента и сервера написание триггеров и хранимых процедур, создание и использование событий базы данных, обработка ошибок в коде на сервере и многое другое. Материал сопровождается многочисленными примерами, советами и практическими рекомендациями.
Для разработчиков баз данных
Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
В вашем обработчике вы выбираете 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() для получения символов возврата каретки и перевода строки */
/* DECLARE EXTERNAL FUNCTION ascii_char
INTEGER
RETURNS CSTRING(1) FREE_IT
ENTRY_POINT 'IB_UDF_ascii_char' MODULE_NAME 'ib_udf'^
COMMIT^
/* Под конец сама хранимая процедура, создающая текстовый файл, эквивалентный приложению 10 данной книги*/
CREATE PROCEDURE OUTPUT ERRCODES
AS
DECLARE VARIABLE SQC SMALLINT;
DECLARE VARIABLE NUM SMALLINT;
DECLARE VARIABLE FAC SMALLINT;
DECLARE VARIABLE SYM VARCHAR(32);
DECLARE VARIABLE TXTVARCHAR(118) ;
DECLARE VARIABLE GDC CHAR(9) CHARACTER SET OCTETS
DECLARE VARIABLE BASEO INTEGER = 335544320;
DECLARE VARIABLE CALCNUM INTEGER;
DECLARE VARIABLE EOL CHAR(2) ;
BEGIN
EOL = ASCII_CHAR(13) || ASCII_CHAR(10);
/* последовательность конца строки */
FOR SELECT
S.SQL_CODE,
S.NUMBER,
S.FAC_CODE,
S. GDS_SYMBOL,
M.TEXT
FROM SYSTEM_ERRORS S
JOIN MESSAGES M
ON
M.FAC_CODE = S.FAC_CODE
AND M.NUMBER = S.NUMBER
AND M.SYMBOL = S.GDS_SYMBOL
/* Устранение некоторых нежелательных/ненужных кодов */
WHERE M.TEXTNOT CONTAINING 'journal'
AND M.TEXTNOT CONTAINING 'dump'
AND s.GDS_SYMBOL NOT CONTAINING 'license'
AND S.GDS_SYMBOL NOT CONTAINING 'wal_'
AND S. GDS_SYMBOLIS NOT NOLL
AND S.SQL_CODE < 102
ORDER BY1 DESC, 2
INTO :SQC, :NUM, :FAC, :SYM, :TXT
DO
BEGIN
/* Тексты сообщений в нижнем регистре, следовательно, мы выполним небольшой трюк для перевода в верхний регистр первой буквы */
IF (TXT IS NULL) THEN
TXT = '(Message unknown)';
ELSE
TXT = UPPER(SUBSTRING(TXT FROM 1 FOR 1)) ||
SUBSTRING(TXT FROM 2);
/* Разработанные значения кодов (FAC_CODE) и чисел NUMBER используются для генерации чисел GDSCODE. Очень просто получить их из последних таблиц SYSTEM_ERRORS и MESSAGES */
IF (FAC IS NOT NULL AND NUM IS NOT NULL) THEN
/* Нам не нужны наполовину приготовленные коды ошибок! */
BEGIN
CALCNUM = BASE0 + (FAC * 65535);
CALCNUM = CALCNUM + NUM + FAC;
GDC = CAST(CALCNUM AS CHAR(9));
INSERT INTO ERRORCODES
VALUES(
/* все переменные поступают в одной строке */
:SQC || ' | ' || :GDC | | ' | ' || :SYM | | ' |' | | :TXT || :EOL) ;
END
END
END ^
COMMIT^
EXECUTE PROCEDURE OUTPUT_ERRCODES ^
COMMIT ^
SET TERM ; ^
/* Текстовый файл теперь готов к обработке текстовым процессором для небольшой корректировки, чтобы избавиться от лишних пробелов, созданных в правой части выходной строки. Быстрый поиск и замена заменят все разделители '|' на ASCII 9 (tab), потому что это было требованием к табуляции для печати. */
События
События Firebird предоставляют механизм сигнализации, с помощью которого хранимые процедуры и триггеры могут передавать сообщения клиентским приложениям, когда другие приложения подтверждают изменения данных. Клиентские приложения устанавливаются в режим "прослушивания" конкретных событий через интерфейс сервер-клиент без системных затрат на опрос наличия изменений.
Читать дальшеИнтервал:
Закладка: