powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / check раньше триггера
17 сообщений из 17, страница 1 из 1
check раньше триггера
    #32179160
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня есть триггер, который при изменении одного поля в главной таблице переписывает строку из одной подчиненной таблицы в другую - то есть в одной стирает, в другой вставляет.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

WBR,
Alexey
...
Рейтинг: 0 / 0
check раньше триггера
    #32181059
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Описание ошибки нашел по адресу 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
check раньше триггера
    #32181086
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то ты там перемудрил. Вот специально сделал пример:

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
check раньше триггера
    #32181162
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо, 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
check раньше триггера
    #32181199
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да уж - химия чистой воды :-)))

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

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

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
17 сообщений из 17, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / check раньше триггера
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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