Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / check раньше триггера / 17 сообщений из 17, страница 1 из 1
08.06.2003, 21:41
    #32179160
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
У меня есть триггер, который при изменении одного поля в главной таблице переписывает строку из одной подчиненной таблицы в другую - то есть в одной стирает, в другой вставляет.

В обоих подчиненных таблицах есть check на значение одного из полей.

Чтоб было понятнее - пример:
Таблица " лица ", " юрлица " и " физлица "
В "лица" поля " код ", " тип ", общие для всех типов поля

В "юрлица" поля " код ", " тип " (check: "тип"='ю'), "краткое наименование", другие характерные для юрлиц поля

В "физлица" поля " код ", " тип " (check: "тип"='ф'), "краткое наименование", другие характерные для физлиц поля

Соответствующие внешние ключи в таблицах "юрлица" и "физлица" с каскадным обновлением.

Пытаюсь сделать триггер, чтобы перед обновлением поля "тип" в главной таблице "код" и "краткое наименование" переписывались в соответствующую таблицу. Однако при изменении типа триггер на обновление срабатывает позже, чем check, который не дает сделать каскадное обновление.

Каков best practice для подобных задач? Может, сделать checkи своими триггерами, у которых я смогу как мне нужно расставить последовательность?

Пардон за таблицы, лица, юрлица и физлица ;)
...
Рейтинг: 0 / 0
09.06.2003, 03:23
    #32179188
StarWind
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
по крайней мере можно решить влоб....
1. Снять check'и с полей таблиц
2. Озаботить этой проверкой триггер
...
Рейтинг: 0 / 0
09.06.2003, 10:40
    #32179294
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Ты наверное IB6 пользуеш. Там была известная бага с тем, что проверки выполнялись до триггеров. Это было давно исправлено в ФБ.
...
Рейтинг: 0 / 0
09.06.2003, 13:10
    #32179472
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Я использую FB 1.0. У меня check срабатывает раньше триггера. А вот тут Алексей Ковязин назвал срабатывание триггера раньше checkа глюком! \r
\r
У меня тогда такой вопрос. Как имеющимися средствами сделать триггер INSTEAD OF?\r
\r
2StarWind: я вот думаю check оставить, но сделать ХП, чтобы менять тип лица. Там сначала будет удаление из одной подчиненной таблицы, потом изменение в главной, потом вставка в другую подчиненную таблицу. \r
\r
И вот, чтобы не беспокоить клиента такими мелочами, я бы попытался вызов этой ХП сделать из триггера INSTEAD OF. Ну если нельзя, то кноечно он будет получать отлуп от checkа, если попытается изменить простым updatом, ничего страшного.\r
\r
Ф.
...
Рейтинг: 0 / 0
09.06.2003, 13:37
    #32179508
check раньше триггера
Привет!

Чеки ДОЛЖНЫ срабатывать РАНЬШЕ триггеров.
Чеки - ограничения более низкого и приоритетного уровня, чем триггеры.

Что касается каскадных обновлений - может, помжет внешний ключ с опцией ON CASCADE ?

WBR,
Alexey
...
Рейтинг: 0 / 0
09.06.2003, 17:24
    #32179819
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
И с чего бы это чекам срабатывать раньше триггеров? Тогда можно будет в таблицу вставлять значения, которые не удовлетворяют проверке.
Смотрите исправленную ошибку 444463.
...
Рейтинг: 0 / 0
09.06.2003, 19:16
    #32179963
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
2Алексей:
Так у меня уже есть ON UPDATE CASCADE. И вот это каскадное обновление-то и не получается - срабатывает чек. У меня и чек, и каскадное обновление, и триггер after update, который должен был выхватить неудовлетворяющую чеку запись и переписать ее в другую таблицу, до срабатывания чека.

2Gold:
не пойму это сарказм или вопрос... ;) Так исправлено или нет? И что написано в 444463? (На последний вопрос можно не отвечать, я и сам посмотрю)

2All: есть ли хитрость, чтобы сделать триггер INSTEAD OF?

Ф
...
Рейтинг: 0 / 0
10.06.2003, 10:41
    #32180250
Roman Ignatiev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
У меня почему-то триггер BEFORE срабатывает раньше всех проверок...
...
Рейтинг: 0 / 0
10.06.2003, 10:59
    #32180273
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Так и должно быть. Если бы триггер BEFORE срабатывал после проверки, в базу можно было бы вставить записи, не удовлетворяющие проверке (т.е. подменить их в триггере). Потом, при попытке восстановления такой базы, случилось бы несчастье. Раньше так и было в IB.
...
Рейтинг: 0 / 0
10.06.2003, 12:02
    #32180350
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Вот теперь я понял, что это действительно ошибка!
Бегу искать обновление...

зы. видимо, на самом деле, чеки должны срабатывать и до, и после триггера (и во время выполнения триггера, чтобы никому не было обидно )
...
Рейтинг: 0 / 0
10.06.2003, 12:24
    #32180388
check раньше триггера
Совсем вы меня запутали :)

Все так, как говорит Gold.

WBR,
Alexey
...
Рейтинг: 0 / 0
11.06.2003, 10:50
    #32181059
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Описание ошибки нашел по адресу http://sourceforge.net/tracker/?func=detail&atid=109028&aid=444463&group_id=9028 , написано, что исправлено в Firebird v.1.0.

У меня, значит, правильная версия стоит.

Видимо, я неправильно делаю, у меня последовательность получается такая.

1. Я меняю в главной таблице "ф" на "ю".
2. Срабатывает каскадное обновление подчиненной таблицы.
3. Проверяется чек подчиненной таблицы, обновление не подходит под чек, выходит исключение
4. До моего триггера "до обновления главной таблицы" выполнение не доходит.

2 выхода, который я попробую, когда доберусь до дома (если не вспомню, что уже пробовал)

1. Уберу каскадное обновление (no action). Скорее всего, тогда при изменении "ф" на "ю" она скажет, что не удовлетворяется внешний ключ, и опять до моего триггера не дойдет.
2. Сделаю вместо триггера в главной таблице триггер "до обновления" в подчиненной таблице, который сотрет запись в своей таблице и запишет ее в другую подчиненную таблицу. Тогда чек, может быть, не успеет ругнуться.

Ф.
...
Рейтинг: 0 / 0
11.06.2003, 11:10
    #32181086
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Что-то ты там перемудрил. Вот специально сделал пример:

CREATE TABLE T1 (F INTEGER CHECK F<0);
CREATE TABLE T2 (F INTEGER CHECK F>0);
SET TERM ^ ;
CREATE TRIGGER T2_BI0 FOR T2
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
IF (NEW.F<0) THEN
NEW.F=NEW.F*-1;
END^
SET TERM ; ^
INSERT INTO T1 VALUES(-1);
INSERT INTO T2 SELECT * FROM T1;

Всё отлично работает...

К стати, советую заюзать функцию типа такой (если под виндой разрабатываешь):

function var i:integer:integer; cdecl;
begin
ShowMessage(IntToStr(i));
Result:=i
end;

Попробуй с помощью неё отладить.
...
Рейтинг: 0 / 0
11.06.2003, 12:01
    #32181162
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Спасибо, Gold, удивляюсь, как не лень делать проверку специально, чтоб кому-то обяснить! Но благодаря ответу мне у тебя перестало быть количество сообщений 666 :)

Но у меня-то немножко по-другому. Конечно я мудрю :) У меня три таблицы, одна главная и 2 подчиненных. Изменение в главной вызывает каскадное обновление одной из подчиненных.

Чтобы абстрагироваться еще больше, можно убрать "главную" таблицу и поставить вопрос так: нужно, чтобы при попытке (до) обновления в таблице 1 брать строку, стирать из таблицы 1 (потому что она не будет удовлетворять чеку) и вставлять в таблицу 2.

например,

CREATE TABLE T1 ( key integer, F INTEGER CHECK F<0);
CREATE TABLE T2 ( key integer, F INTEGER CHECK F>0);

SET TERM ^ ;
CREATE TRIGGER T2_B U 0 FOR T2
ACTIVE BEFORE UPDATE POSITION 0
AS
BEGIN
IF (NEW.F<0) THEN
insert into T1 (key, F) values (new.key, new.F);
delete T1 where F=old.key;

/* и видимо, update после этого просто ничего не сделает, т.е. не попытается изменить F на отрицательное, потому что не найдет ключа */
END^
SET TERM ; ^

и теперь когда мы попробуем сделать

update T2 set F=F*-1 where key=123

то запись с key=123 перескочит в T1 (вот этого мне и надо добиться)

Будет ли так работать?
...
Рейтинг: 0 / 0
11.06.2003, 12:34
    #32181199
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Да уж - химия чистой воды :-)))

Тут решений я вижу 2:

1. делать через обновление через процедуру и всё котролировать в ней
2. убрать чеки и всё выполнять в последних триггерах ПОСЛЕ обновления
...
Рейтинг: 0 / 0
11.06.2003, 12:53
    #32181235
fedd
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
А че, так как я написал, не будет работать? Уже видно?
Конечно, сделаю проце дуру, если не будет, но чеки оставлю все-таки..
...
Рейтинг: 0 / 0
11.06.2003, 13:17
    #32181277
Gold
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
check раньше триггера
Ну, предположим, вот так оно работать будет:

BEGIN
IF (NEW.F<0) THEN
BEGIN
INSERT INTO T1 VALUES (NEW.F);
NEW.F=NEW.F*-1;
DELETE FROM T2 WHERE F=OLD.F;
END
END

Только стрёмно это. Мало ли чего. Я бы так не рискнул делать.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / check раньше триггера / 17 сообщений из 17, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]