Зацикливание триггера

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

Ответить
McArty
Сообщения: 56
Зарегистрирован: 14 янв 2005, 09:31

Зацикливание триггера

Сообщение McArty » 14 янв 2005, 10:44

Есть триггер на Update,точнее After Update. Он обновляет данные в этой же таблице, ну и соответственно возникает бесконечный цикл.
Можно ли как-то обойти эту проблему в тригере. Пока данная задача решена в клиентской проге, но хотелось бы перенести эту задачу на сервер.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 янв 2005, 10:54

а не надо писать так, чтобы была рекурсия :)
на самом деле это нехорошо - в after update обновлять эту же таблицу. с проверкой рекурсии или без. думаю, что тебе придется добавлять столбец-индикатор, чтобы не происходил зацикл.

McArty
Сообщения: 56
Зарегистрирован: 14 янв 2005, 09:31

Сообщение McArty » 14 янв 2005, 11:01

Тогда с самого начала:
Есть таблица Skidki(ID,Name и т.п.)
И таблица правил суммирования скидок, т.е. какая скидка с какой может складываться. SkidkiSumm(ID,ID2,Flag). Соответственно,
если Sk№1 не складываеться со скидкой №3,то и скидка №3 не складывается со скидкой №1. Поэтому и хотел сделать триггер, так как это более логично. Хотя проблема может быть и в не правильном представлении данных, по таблицам.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 14 янв 2005, 12:01

McArty писал(а):Тогда с самого начала:
Есть таблица Skidki(ID,Name и т.п.)
И таблица правил суммирования скидок, т.е. какая скидка с какой может складываться. SkidkiSumm(ID,ID2,Flag). Соответственно,
если Sk№1 не складываеться со скидкой №3,то и скидка №3 не складывается со скидкой №1. Поэтому и хотел сделать триггер, так как это более логично. Хотя проблема может быть и в не правильном представлении данных, по таблицам.
Представление на мой взгляд правильное. Что логичнее - делать изменения только через процедуру, или только запросом с where типа
(ID=:SK1 And ID2=:SK2) Or (ID=:SK2 And ID2=:SK1) или всё-таки застраховаться от собственного склероза в триггере - трудно сказать. Но тогда эту логику лучше перенести в Before триггера и добавить в таблицу флаг, скажем FlTrigger Char(1) Default 'N' (не забыть сразу установить его в N в существующих записях). И тела триггеров вида

As
Begin
if (New.FlTrigger='N') then
begin
...
Update This_Table Set FlTrigger='Y', ...
Where ... ;
...
end
New.FlTrigger='N';
End

то есть, когда он Y, триггер делает только обратную установку его в N, в базе он всегда остаётся N и позволяет блокировать рекурсию.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 янв 2005, 12:16

просветите, зачем это в триггере делать надо? тем более что SkidkiSumm(ID,ID2,Flag) уже и так выглядит как вызов процедуры, в которой делается просто инсерт или update двух записей.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 14 янв 2005, 12:23

kdv писал(а):просветите, зачем это в триггере делать надо? тем более что SkidkiSumm(ID,ID2,Flag) уже и так выглядит как вызов процедуры, в которой делается просто инсерт или update двух записей.
Ну вот скажем пришёл я с бодуна 11 числа и с трёх сторон сели на уши, второпях и спорол хню, махнул запросом вместо процедуры не глядя и забыл про вторую запись. А триггер - не даст. В общем-то и всё :)

Лысый
Сообщения: 177
Зарегистрирован: 08 ноя 2004, 08:20

Сообщение Лысый » 14 янв 2005, 12:33

Merlin писал(а):Ну вот скажем пришёл я с бодуна 11 числа и с трёх сторон сели на уши, ...
Похоже случай из жизни :lol:

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 янв 2005, 14:01

понятно. т.е. вместо написания элементарной процедуры начинается траходром с рекурсивным триггером... :)

McArty
Сообщения: 56
Зарегистрирован: 14 янв 2005, 09:31

Сообщение McArty » 14 янв 2005, 14:06

kdv писал(а):понятно. т.е. вместо написания элементарной процедуры начинается траходром с рекурсивным триггером... :)
Ну это как сказать, что если потом др. прогер будет писать клиентскую часть, и ему будет ПХ эта самая процедура.А тригер,он по идеи, и предназначен для того,что бы следить за целостностью информации в базе, или я не прав?
Merlin,сенкс за пример.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 янв 2005, 14:23

контроль сущности (то есть создание взаимосвязи экземпляров сущности, т.е. записей таблицы, тем более рекурсивной связи) при версионности вещь весьма опасная.
Это описано в http://www.osp.ru/os/2003/02/059_print.htm (пример write skew)

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

Короче, я на эту тему высказался, а дальше уже личное дело каждого :)

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

McArty
Сообщения: 56
Зарегистрирован: 14 янв 2005, 09:31

Сообщение McArty » 14 янв 2005, 14:27

За статью спасибо :)

sag
Сообщения: 116
Зарегистрирован: 02 ноя 2004, 11:42

Сообщение sag » 14 янв 2005, 14:28

Согласен с kdv. А с бодуна даже тригерное предохранение может не помочь :)

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 14 янв 2005, 14:44

kdv писал(а):контроль сущности (то есть создание взаимосвязи экземпляров сущности, т.е. записей таблицы, тем более рекурсивной связи) при версионности вещь весьма опасная.
Это описано в http://www.osp.ru/os/2003/02/059_print.htm (пример write skew)
Статью читать влом, но имхо насчёт сущностей ты здесь не в тему. Здесь похоже элементарный m:n ссылающийся на одну и ту же таблицу обоими концами, но с дублированием записей с переставленными местами ключами, чтобы не чесать репу - тот, от которого сейчас ищем пару содержится в m:n в поле А или в поле Б и искать с любого конца. Вариант упрощающей запрос денормализации, тянущий за собой накладные расходы при модификациях из-за update-парадокса. Правда когда там не пары, а множества, становится громоздко. Я бы в таком случае сложил бы эти множества в одно поле - всё в ту же строку с разделителем и искал бы containing'ом.
kdv писал(а): а по поводу прогера, которому ПХ процедура - ему также ПХ будет и этот триггер, не поняв смысла которого он может изменить или вообще удалить. Процедурой хоть можно запретить впрямую редактировать таблицу, между прочим.
Себе-то? :wink: Я ж говорю - защита от бодуна. Я, кстати, вообще везде такое поле держу и триггера все так оформляю, на случай аврийной правки отдельных записей, требующей отключения триггеров, при живых юзерах, не рискуя с inactive-active и никому не мешая.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 янв 2005, 14:59

по поводу "За статью спасибо" буянить буду - все это уже давно лежит на www.ibase.ru/develop.htm, в разделе про транзакции.
я дал прямую ссылку только потому, что write skew проверял на наличие именно в 4-ой части.

McArty
Сообщения: 56
Зарегистрирован: 14 янв 2005, 09:31

Сообщение McArty » 14 янв 2005, 15:07

kdv писал(а):по поводу "За статью спасибо" буянить буду - все это уже давно лежит на www.ibase.ru/develop.htm, в разделе про транзакции.
я дал прямую ссылку только потому, что write skew проверял на наличие именно в 4-ой части.
Да. да. вот не читают люди, а потом с вопросами в Forum лезут(каюсь).

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 14 янв 2005, 16:04

я не сильно ругаюсь, так, ворчу. :)
но Merlin правильно сказал, что это не совсем то что в статье. Хотя и то и это - контроль на уровне сущности, а я этого сильно не люблю...

кстати, тот пример из статьи решается отдельной таблицей с 1-ой записью и update этой таблицы, с exception в триггере если сумма больше нужной.

В запросе про взаимосвязь скидок мне наоборот, не понравились циклические ссылки между записями :-)

Ответить