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

Откуда: Гондурас
Сообщений: 1025
Уважаемый форум,

Простой вопрос: предположим создается триггер After Update для отслеживания изменений в нескольких полях таблицы. Далее, необходимо, чтобы одна часть триггера реагировала на изменение любого из полей, указанных в списке, а отдельные инструкции выполнялись исключительно при изменении только одного конкретного поля из списка. Отсюда возможна ли следующая структура триггера:
ALTER TRIGGER [dbo].[Trigger_Inspection_Scoring] 
   ON  [dbo].[tbl_Inspection] 
   AFTER UPDATE
AS	DECLARE @...
IF UPDATE(Field 1) OR UPDATE(Field 2) ... OR UPDATE (Field N)
BEGIN
...
END
IF UPDATE(Field 1)
BEGIN
...
END
IF UPDATE(Field 2)
BEGIN
...
END

Если нет, то подскажите, пожалуйста, как можно реализовать такую структуру?
Спасибо заранее!
11 мар 14, 18:52    [15706579]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
trigger after update
Guest
1. триггер срабатывает на операцию целиком а не на каждую измененную строку
2. внутри триггера можно обращаться к виртуальным таблицам inserted/deleted, в которых есть значения полей до и после операции update
11 мар 14, 18:59    [15706611]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
IFK
Member

Откуда: Гондурас
Сообщений: 1025
trigger after update
1. триггер срабатывает на операцию целиком а не на каждую измененную строку
2. внутри триггера можно обращаться к виртуальным таблицам inserted/deleted, в которых есть значения полей до и после операции update


1. На какую операцию целиком? По-моему, именно что на изменение записи в таблице.

2. Хм, это понятно, но не содержит ответа на мой вопрос. Повторюсь: мне необходимо, чтобы при срабатывании триггера, скажем, при изменении Field 2 отрабатывали инструкции из первой части IF UPDATE(Field 1) OR UPDATE(Field 2) etc., а затем инструкции из части, касающейся только изменения Field 2 => IF UPDATE(Field 2).

Вы же мне предлагаете, насколько я понял, проверять изменилось ли поле Field 2, базируясь на временных таблицах Inserted/Deleted, так? А какой тогда смысл в триггере, срабатывающем при изменении определенного поля? Можно просто в любом триггере проверять таблицы Inserted/Deleted и не мучать себя и сервер.
11 мар 14, 19:16    [15706682]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4424
IFK
На какую операцию целиком? По-моему, именно что на изменение записи в таблице.

Имейте в виду, что триггер срабатывает на операцию UPDATE таблицы, а не отдельной записи!
Если UPDATE затрагивает несколько записей, то вы не сможете отловить каждое изменение.
11 мар 14, 19:32    [15706750]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4424
Вообще выскажу свое мнение, что вешать логику в триггер это как-то совсем некошерно.
Понимаю, что бывают ситуации, когда нужно хитро вывернуться, но лучше их избегать.
Представьте себе, что внутри триггера вносятся изменения в другую таблицу...
А там тоже триггер, который меняет данные в 3-й таблице...
11 мар 14, 19:37    [15706773]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
IFK
Member

Откуда: Гондурас
Сообщений: 1025
SQL2008
IFK
На какую операцию целиком? По-моему, именно что на изменение записи в таблице.

Имейте в виду, что триггер срабатывает на операцию UPDATE таблицы, а не отдельной записи!
Если UPDATE затрагивает несколько записей, то вы не сможете отловить каждое изменение.


Ну, в этом случае ничего не остается, кроме как отлавливать изменения полей в цикле по записям Inserted/Deleted. Тогда вопрос снимается - хотел избежать многоступенчатых проверок, тем более в теле цикла. Буду искать решение на стороне фронт-энда.

Всем спасибо!
11 мар 14, 20:03    [15706874]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
invm
Member

Откуда: Москва
Сообщений: 9724
SQL2008
Если UPDATE затрагивает несколько записей, то вы не сможете отловить каждое изменение.
Это почему?
11 мар 14, 20:13    [15706909]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
SQL2008
Member

Откуда: Москва
Сообщений: 4424
invm
SQL2008
Если UPDATE затрагивает несколько записей, то вы не сможете отловить каждое изменение.
Это почему?

Допустим в таблице [Table] есть несколько значений в поле [Field]
1,2,4,7,8,2,5
Триггер срабатывает на
UPDATE [Table] SET [Field] = 2


Если пытаться определить, что изменилось поле сравнивая значения [Table].[Field] и [inserted].[Field]
(а как я понял была именно такая идея автора),
то всегда ли вы сможете выловить момент когда [Table].[Field] <> [inserted].[Field] ?
11 мар 14, 20:23    [15706964]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
invm
Member

Откуда: Москва
Сообщений: 9724
SQL2008,

use tempdb;
go

create table [Table] (id int identity, field int);
insert into [Table] (field) values (1), (2), (4), (7), (8), (2), (5);
go

create trigger trTable_OnUpdate
on [Table]
for update
as
begin
 set nocount on

 if not exists(select 1 from inserted)
  return;

 select
  i.field as new_filed, d.field as old_field
 from
  inserted i join
  deleted d on d.id = i.id
 where
  not exists(select i.field intersect select d.field);
end;
go

update [Table] set field = 2;
go
 
drop table [Table];
go
11 мар 14, 20:42    [15707054]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
iap
Member

Откуда: Москва
Сообщений: 47085
SQL2008
invm
пропущено...
Это почему?

Допустим в таблице [Table] есть несколько значений в поле [Field]
1,2,4,7,8,2,5
Триггер срабатывает на
UPDATE [Table] SET [Field] = 2



Если пытаться определить, что изменилось поле сравнивая значения [Table].[Field] и [inserted].[Field]
(а как я понял была именно такая идея автора),
то всегда ли вы сможете выловить момент когда [Table].[Field] <> [inserted].[Field] ?
Тема - феерический бред!
Во-первых, функция UPDATE() не имеет ничего общего с изменением данных.
Она лишь показывает, было ли поле в списке SET команды UPDATE.
В-третьих, inserted и эти же записи самой таблицы всегда совпадают в триггере AFTER UPDATE.
В-четвертых, изменения надо определять по deleted и inserted,
для этого у таблицы обязательно должен быть неизменяемый уникальный ключ.
И т.д.
11 мар 14, 20:46    [15707077]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
iap
Member

Откуда: Москва
Сообщений: 47085
SQL2008
Вообще выскажу свое мнение, что вешать логику в триггер это как-то совсем некошерно.
Понимаю, что бывают ситуации, когда нужно хитро вывернуться, но лучше их избегать.
Представьте себе, что внутри триггера вносятся изменения в другую таблицу...
А там тоже триггер, который меняет данные в 3-й таблице...
Сто раз вешал.
Главное - чувство меры.
11 мар 14, 20:58    [15707130]     Ответить | Цитировать Сообщить модератору
 Re: Несколько условий в триггере After Update  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
IFK
Повторюсь: мне необходимо, чтобы при срабатывании триггера, скажем, при изменении Field 2 отрабатывали инструкции из первой части IF UPDATE(Field 1) OR UPDATE(Field 2) etc., а затем инструкции из части, касающейся только изменения Field 2 => IF UPDATE(Field 2).
Можно просто в любом триггере проверять таблицы Inserted/Deleted и не мучать себя и сервер.
Я такое "извращение" делал.
И путём использования функции UPDATE и путём использования COLUMNS_UPDATED()

Но я бы для начало спросил для чего Вы это делаете ?

К примеру я так контролировал действия над объектом. В зависимости от состояния легитимны только определённый набор действий над определёнными его свойствами.
Но это больше несёт смысл на стадии разработки и для контроля. И для этого использование проверки списка колонок в SET считаю оправданным.

Ещё был вариант определить по данной комбинации намерение, которое приводит к разным действием.
Эдакое вывернутое на изнанку, завуалированное, закодированное действие. Вот это то ещё извращение.

Иногда используется когда часть таблы отражает некоторый общий/отдельный механизм и его надо на него "отразить".
Но обычно надо просто перечислить набор колонок которые при нём затрагиваются. Пересечения редки.

SQL2008, я делал системы где триггера это везде и повсеместно. Ничего, проблем не было. Никаких. Системы были более устойчивыми.
Проблемы есть когда надо вешать триггера на логические сущности, когда физическое отображение его в базе сильно разделено (много таблиц). И при этом использовать один общий вундер интерфейс - представление не всегда удобно.
К примеру механизм IDENTITY уже не работает, не получить его значение через OUTPUT или Scope_Identity(), только в 2012 появились SEQUENCE (и то, чисто числовые).

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

Иногда проще рассматривать объект как сущность и действие над ним это просто тупо изменение его свойств (одно действие).
Но иногда это целый процесс - нобор совершенно разных действий.
И лучше это не смешивать, и не путать.

PS: И да, UPDATE() и COLUMNS_UPDATED() это просто вспомогательные функции, а не ключевые слова определения триггера (на выполнение команды, а не на изменение данных, строк может быть и ноль).
11 мар 14, 23:34    [15707732]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить