Страница 1 из 1

обработка исключений на сервере.

Добавлено: 06 янв 2007, 15:58
Dixi
Привет всем.
интересует как сделать следующее:
есть 2 таблицы подчиненные как "один ко многим" через foreign key.
при удалении из справочной таблицы элемента который еще используется в основной таблице возникает исключение violation of FOREIGN KEY constraint.
хочется вместо системного вызвать свое исключение.

есть вариант сделать так

Код: Выделить всё

CREATE EXCEPTION ON_DEL_CURRENCY 'Удаление невозможно, блаблабла';

CREATE TRIGGER DEL_CURRENCY FOR CURRENCIES
ACTIVE BEFORE DELETE POSITION 0
AS
DECLARE VARIABLE CNT INTEGER;
begin
  SELECT COUNT(*) FROM PAYMENTS WHERE  PAYMENTS.CURRENCYID=OLD.CURRENCYID INTO CNT;
  IF (CNT>0) THEN EXCEPTION ON_DEL_CURRENCY;
end
но на каждое удаление выполнять запрос, как я понимаю, сильно затормозит базу, если будет использоваться на больших объемах данных.

можно ли вызвать своё исключение, основываясь на коде возвращенной ошибки? например в триггере вызываемом after delete?
типа
when sqlcode -NNN
DO
EXCEPTION ON_DEL_CURRENCY;
где NNN код системной ошибки.
(предыдущий код сам по себе в триггере не работает, это так размышления в слух.)

Добавлено: 06 янв 2007, 16:03
kdv
не будет это работать. FK работают вне транзакций, а триггер - в контексте транзакции оператора, его вызвавшего. Поэтому FK заменять подобными триггерами категорически не рекомендуется.
Проще отловить на клиенте эту ошибку, и перевести ее так, как нужно пользователю.

p.s. описанная Вами попытка "замены" exception - изврат натуральный.

Добавлено: 06 янв 2007, 22:42
Dixi
заметте, что то, что вы сказали я собственно сказал и сам, давайте не заниматься тавтологией. меня как раз интересует как это сделать без клиента, мне клиент вообще мало интересен. Мало ли на чем его будут писать - мне надо по максимуму все описать на сервере.

хорошо, а как тогда в триггере узнать прошла ли транзакция или нет?
зачем тогда вообще триггера типа after delete?

Добавлено: 06 янв 2007, 23:48
kdv
в триггере - никак. триггер выполняется до контроля FK или после. И триггер либо выполняется, либо не выполняется. Например, если есть 2 триггера на одно действие, и в первом произошла ошибка, второй триггер не будет выполняться вообще - иначе поведение сервера можно было бы посчитать идиотским.
Поэтому, никакие внешние ошибки, происходящие вне триггеров, в триггеры не могут попасть ни коим образом и ни в каком виде.

Точно так же, ни в каком операторе sql нельзя узнать "прошла транзакция" или нет, потому что транзакции находятся на более "высоком" уровне, чем sql-операторы (хотя здесь я не совсем точен, ибо в FB 2.1 обещают триггеры на commit).

Триггеры after delete нужны для того, чтобы например выполнить какое-либо действие, которое должно выполниться после успешного (!) удаления - например, сделать запись в таблицу "лога" об этом удалении, послать клиенту event, и т.п.

p.s. я тавтологией не занимаюсь ни в коей мере. В текущей реализации сервера сообщения о нарушениях контроля PK, FK и unique являются "универсальными". Попытка сделать их "менее уникальными" понятна, но в отношении constraints осуществима только в клиентском приложении - самостоятельно или при помощи таких средств как репозитарий FIBPlus и т.п.

Добавлено: 07 янв 2007, 00:19
Dixi
kdv писал(а): В текущей реализации сервера сообщения о нарушениях контроля PK, FK и unique являются "универсальными". Попытка сделать их "менее уникальными" понятна, но в отношении constraints осуществима только в клиентском приложении - самостоятельно или при помощи таких средств как репозитарий FIBPlus и т.п.
понятно :(
спасибо за ликбез.
как я понимаю, такая же ситуация и с определением исключений при инсерте когда происходит нарушение уникальности?

Добавлено: 07 янв 2007, 11:29
kdv
как я понимаю, такая же ситуация и с определением исключений при инсерте когда происходит нарушение уникальности?
натюрлих.

p.s. вообще если делать вставку, обновление или удаление процедурой, то в ней можно обрабатывать ошибки. в datadef.pdf есть пример.

Добавлено: 07 янв 2007, 16:09
Dixi
kdv писал(а): вообще если делать вставку, обновление или удаление процедурой, то в ней можно обрабатывать ошибки. в datadef.pdf есть пример.
да , я думал об этом варианте, но в этом случае теряется прозрачность управления данными. также неудобны будут массовые вставки и удаления. жаль конечно, но придется кое что выносить на клиента.