Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите плз разобраться с триггерами.  [new]
abrashka
Member

Откуда:
Сообщений: 517
День добрый!
Помогите плз правильно построить триггеры в такой ситуации:
Существует таблица MyTbl, если в ней происходит изменение, то должно поменяться поле LastUpdateRowVersion в измененной строке, кроме того, Id измененной строки должно записаться в таблицу AuditTbl.
За первую задачу отвечает триггер trg_1, а за вторую trg_2. Соеденить оба действия в один тиггер нельзя по определенным соображениям.
Возникает ситуация, при которой при изменении какойто строки выскакивает оба триггера, но т.к. первый сам изменяет эту же строку, то второй триггер выскакивает еще раз. Это можно проследить на примере.
Вопрос как "правильно" создать второй триггер, чтоб он не реагировал на изменения, которые сделал первый.
Спасибо!

if object_id('MyTbl') is not null drop table MyTbl;
create table MyTbl
(id int, n int, LastUpdateRowVersion binary(8));

insert into MyTbl(id,n)
values (1,1),(2,2),(3,3),(4,4),(5,5);

--select * from MyTbl;

if object_id('AuditTbl') is not null drop table AuditTbl;
create table AuditTbl(id int);
go

CREATE TRIGGER trg_1 ON MyTbl
AFTER UPDATE
AS
UPDATE MyTbl
SET LastUpdateRowVersion = @@DBTS
FROM MyTbl T INNER JOIN inserted I ON T.id = I.id;
go

CREATE TRIGGER trg_2 ON MyTbl
AFTER UPDATE
AS
INSERT INTO  AuditTbl
select id from inserted;
go
/******************************************/
--select * from MyTbl
--select * from AuditTbl
--;
update MyTbl
set  n=999 
where id in (2,4)
;
select * from MyTbl
select * from AuditTbl
5 янв 15, 18:58    [17087219]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
Crimean
Member

Откуда:
Сообщений: 13148
а тип данных timestamp / rowversion - "для слабых духом" (ц)?
5 янв 15, 18:59    [17087220]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
abrashka
Member

Откуда:
Сообщений: 517
Т.е. ожидаю получить в таблице AuditTbl две строки, а получаю четыре, т.к. второй триггер выскакивает дважды.
Картинка с другого сайта.
5 янв 15, 19:05    [17087235]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
Crimean
Member

Откуда:
Сообщений: 13148
abrashka
второй триггер выскакивает дважды


потому что UPDATE для таблички происходит 2 раза. первый раз - по инициативе "пользователя", второй раз - по инициативе триггера. вот и получаете 2 "срабатывания"
5 янв 15, 19:07    [17087239]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
abrashka
Member

Откуда:
Сообщений: 517
Crimean,

Ну это понятно... Поэтому и спрашиваю, как во втором триггере игнотировать изменения первого.
5 янв 15, 19:11    [17087246]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
abrashka
Member

Откуда:
Сообщений: 517
Crimean
а тип данных timestamp / rowversion - "для слабых духом" (ц)?


В моем случае в таблице с миллионами строк, в которой изменения происходят очень редко, нет смысла "содержать" timestamp / rowversion.
5 янв 15, 19:33    [17087301]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
invm
Member

Откуда: Москва
Сообщений: 9404
Варианты:
а) пересмотреть соображения, по которым нельзя объединить триггеры.
б) вынести обновление LastUpdateRowVersion и запись в AuditTbl в отдельный триггер instead of update.
в) проверять в trg_2 уровень вложенности функцией trigger_nestlevel.
5 янв 15, 19:34    [17087303]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
Crimean
Member

Откуда:
Сообщений: 13148
abrashka,

а и зря вы timestamp сами эмулируете. да еще и так криво.
5 янв 15, 19:58    [17087380]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
abrashka
Crimean
а тип данных timestamp / rowversion - "для слабых духом" (ц)?


В моем случае в таблице с миллионами строк, в которой изменения происходят очень редко, нет смысла "содержать" timestamp / rowversion.
Зато вы "содержите" уродский и ненужный триггер.
5 янв 15, 22:40    [17087794]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
abrashka
Member

Откуда:
Сообщений: 517
На счет объединить триггеры- возможна ситуация, когда один из триггеров нужно будет отменить или включить.
На счет timestamp, как и говорил выше, есть относительно большие таблицы, данные в которых не изменяются, а задача отфильтровать только измененные данные, т.е. там где LastUpdateRowVersion is not null


invm,
Спасибо!!!
В моем случае самый приемлимый вариант- это использование trigger_nestlevel во втором триггере, добавил
IF trigger_nestlevel() > 1 RETURN и теперь он выскакивает только один раз.

На самом деле мою конкретную проблему это решило только частично(есть дедлок, но об этом в другой теме), а для себя узнал новую фичу.

Спасибо!
6 янв 15, 11:54    [17088752]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
Glory
Member

Откуда:
Сообщений: 104760
abrashka
В моем случае самый приемлимый вариант- это использование trigger_nestlevel во втором триггере, добавил
IF trigger_nestlevel() > 1 RETURN и теперь он выскакивает только один раз.

Ага. Если позже в один прекрасный момент yTbl начнет обновляться из другого триггера, то ваша проверка молча "заткнет" выполнение
6 янв 15, 11:59    [17088768]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
abrashka
Member

Откуда:
Сообщений: 517
Glory,

Спасибо!
Об этом на самом деле я не подумал, но пока не предвидется обновление таблицы при помощи другого триггера.
Я тоже склоняюсь к объединению в один триггер, будем посмотреть....
6 янв 15, 12:15    [17088809]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
invm
Member

Откуда: Москва
Сообщений: 9404
abrashka
IF trigger_nestlevel() > 1 RETURN
Почитайте, что возвращает вызов trigger_nestlevel без параметров. В вашем случае нужно:
IF trigger_nestlevel(@@procid) > 1 RETURN
6 янв 15, 12:19    [17088820]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
Glory
Member

Откуда:
Сообщений: 104760
abrashka
но пока не предвидется обновление таблицы при помощи другого триггера.

Когда это произойдет - никто ничего и не узнает.
Ваш же триггер просто будет игнорировать такие вызовы
6 янв 15, 12:20    [17088821]     Ответить | Цитировать Сообщить модератору
 Re: Помогите плз разобраться с триггерами.  [new]
petre
Member

Откуда: Кривой Рог
Сообщений: 42
Может так попробовать?
INSERT INTO  AuditTbl
select i.id from inserted i
inner join deleted d
on i.id=d.id
where i.LastUpdateRowVersion=d.LastUpdateRowVersion;
6 янв 15, 12:44    [17088908]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить