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

Откуда: Astana City
Сообщений: 21
Добрый день!
Есть триггер, который срабатывает на UPDATE и проверяет было ли изменено значение колонки Column1 и если да, то вызываем функцию func1:

ALTER TRIGGER [dbo].[update_documents] 
   ON [dbo].[Documents]
   AFTER UPDATE
AS
BEGIN
	DECLARE @Id nvarchar(MAX)
	DECLARE @Column1 nvarchar(MAX)

	if (update(Column1))
	BEGIN
		SET @Id = (SELECT Id FROM inserted)
		SET @Column1 = (SELECT Column1 FROM inserted)
		EXECUTE func1 @Id, @Column1
	END
END

Работает отлично при апдейте ОДНОЙ строки в таблице Documents

Собираюсь переписать представленный выше триггер с использованием курсоров, для того чтобы пробегать в цикле все строки, которые были изменены:

ALTER TRIGGER [dbo].[update_documents] 
   ON [dbo].[Documents]
   AFTER UPDATE
AS
BEGIN
	DECLARE @Id nvarchar(MAX)
	DECLARE @Column1 nvarchar(MAX)

	DECLARE cur CURSOR LOCAL FOR
	SELECT  Id, Column1
	FROM inserted

	OPEN cur
    
	FETCH NEXT FROM cur INTO
	@Id, @Cursor1

	WHILE @@FETCH_STATUS = 0
	BEGIN

		if (update(Column1))
		BEGIN
			SET @Id = (SELECT Id FROM inserted)
			SET @Column1 = (SELECT Column1 FROM inserted)
			EXECUTE func1 @Id, @Column1
		END

		FETCH NEXT FROM cur INTO
		@Id, @Cursor1
	END
	CLOSE cur
	DEALLOCATE cur
END

ВОПРОС: Правильно ли будет работать функция update(Column1) и брать Column1 в соответствии с курсором cur
9 авг 11, 15:24    [11092149]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Kairat V. Beysenov,

1. функция UPDATE() возвращает TRUE, если поле было в списке полей команды UPDATE. Иначе возвращает FALSE.
Независимо от того, изменились данные или нет!
2. Какой смысл в вызове функции? Может,это всё же процедура?
9 авг 11, 15:36    [11092255]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Kairat V. Beysenov
Member

Откуда: Astana City
Сообщений: 21
iap, спс за ответ!
1. То что вы написали про функцию UPDATE() я знаю. Скорее всего не верно сформулировал мысль в первом посте.

2. Вы спрашиваете про смылс вызова func1? В ней смысла много для моего приложения :) И выполняться она должна только если вызывался апдейт на поле Column1.

П.С. Да и сам триггер я очень упростил. Ведь вопрос не в вызове func1, а в правильности возврата ответа UPDATE().
9 авг 11, 15:52    [11092396]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Shakill
Member

Откуда: мск
Сообщений: 1887
Kairat V. Beysenov, а что значит "в соответствии с курсором"? ведь набор столбцов в операторах UPDATE и INSERT задается один для всего набора данных
9 авг 11, 15:58    [11092450]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Kairat V. Beysenov
2. Вы спрашиваете про смылс вызова func1? В ней смысла много для моего приложения :)
Функция не может давать побочных эффектов и оставлять следы своей работы где бы то ни было.
Она может вернуть значение определённого типа (скалярная UDF) или рекордсет (табличная UDF).
Но в Вашем триггере и то и другое "улетает в трубу". Смысла в этом никакого.

Про UPDATE() повторю: смысл в её применении практически нулевой.
9 авг 11, 16:08    [11092545]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Kairat V. Beysenov
Member

Откуда: Astana City
Сообщений: 21
Так, я всё понял!
Shakill, прочитав ваше сообщение и проверив работу триггера с курсором для разных UPDATE - я понял что я переборщил в своих мыслях об UPDATE().
Попытаюсь рассказать что я там навыдумавал и поэтом написал update в соответствии с курсором:
Допустим мы обновили две строки, соответсвтенно в таблице inserted будет две записи. И вооот мою мысль уже было неостановить... Я решил, что функция UPDATE() должна для каждой строки из inserted возвращать соответствующие значения. И у меня это не вязалось с синтаксисом функции UPDATE() так как там просто указывается наименование колонки.

Сейчас я привел свои мысли в кучу и подтвердил это тестами и вашими сообщениями о том, что я что-то перемудрил!

Всем спс!
Вопрос исчерпан, все свободны :)
9 авг 11, 16:10    [11092566]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Kairat V. Beysenov
Member

Откуда: Astana City
Сообщений: 21
ALTER TRIGGER [dbo].[update_documents] 
   ON [dbo].[Documents]
   AFTER UPDATE
AS
BEGIN
	DECLARE @Id nvarchar(MAX)
	DECLARE @Column1 nvarchar(MAX)

	if (update(Column1))
	BEGIN
		SET @Id = (SELECT Id FROM inserted)
		SET @Column1 = (SELECT Column1 FROM inserted)
		EXECUTE func1 @Id, @Column1
	END
END

iap, я верно вас понял: вы утверждаете что в данном коде update(Column1) лишний?
А если я изменю другое поле таблицы Documents то зачем мне тогда вызывать func1 - лишняя нагрузка.

П.С. Мы правильно вообще друг друга понимаем, говоря об одном или о разном всё-таки?
9 авг 11, 16:16    [11092628]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Kairat V. Beysenov
Member

Откуда: Astana City
Сообщений: 21
iap, может дело в том что я не верно назвал func1 функцией, а это на самом деле хранимая процедура.
Если дело в этом, то прошу прощения, что завел вас в замешательство, своей безграмотностью =)
9 авг 11, 16:19    [11092648]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
Kairat V. Beysenov
iap, может дело в том что я не верно назвал func1 функцией, а это на самом деле хранимая процедура.
Если дело в этом, то прошу прощения, что завел вас в замешательство, своей безграмотностью =)
А я сразу так и подумал (см. второе сообщение темы)
9 авг 11, 16:20    [11092665]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Kairat V. Beysenov
Member

Откуда: Astana City
Сообщений: 21
Почитал форум и все говорят, что использование курсоров надо избегать.
А что собственно плохого в их использовании для таблиц inserted или deleted в триггерах?
9 авг 11, 18:29    [11093651]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
Kairat V. Beysenov
Почитал форум и все говорят, что использование курсоров надо избегать.
А что собственно плохого в их использовании для таблиц inserted или deleted в триггерах?

Если читали , то там же писано почему. Медленно потому что.
9 авг 11, 18:39    [11093685]     Ответить | Цитировать Сообщить модератору
 Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
SamMan
Member

Откуда: Moscow
Сообщений: 759
Kairat V. Beysenov
А что собственно плохого в их использовании


Если абстрагироваться от СУБД (любой) то мы узнаем, что при работе с данными в принципе возможны две методологии, или логики работы:
  • set-based logic - работаем сразу с набором данных (то что и делают селекты/апдейты/...)
  • row-based logic - работаем с каждой строкой персонально (как раз курсоры)

    Так вот движок нашего сервера создавался, проектировался, оптимизировался и вообще "затачивался" под логику N1. А с логикой N2 он только способен (синтаксически) работать при этом теряя всю эффективность и оптимальность работы с наборами.
    Так, как-то...
  • 9 авг 11, 19:07    [11093794]     Ответить | Цитировать Сообщить модератору
     Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
    Kairat V. Beysenov
    Member

    Откуда: Astana City
    Сообщений: 21
    Если курсоры медленны, то каким образом можно обойти в цикле все записи таблицы inserted?
    При условии что триггер вызывается на таблицу с количеством полей равным 100.
    Создавать временную таблицу с добавлением int-ового идентификатора к существующим ста колонкам не логично...

    В моем случае количество записей в inserted будет исчисляться 10-50 записями.
    9 авг 11, 21:07    [11094101]     Ответить | Цитировать Сообщить модератору
     Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
    Шыфл
    Member

    Откуда: Прага
    Сообщений: 776
    Kairat V. Beysenov
    Если курсоры медленны, то каким образом можно обойти в цикле все записи таблицы inserted?

    Это в корне не правельная постановка вопроса. Логичнее было бы спросить: "Как без цикла обработать все записи таблицы inserted с помощью моей процедуры func1?" Ответ: "Изменить логику работы с данными, что бы не по строчке таблицу inserted обрабатывать, а сразу всю".
    9 авг 11, 21:23    [11094144]     Ответить | Цитировать Сообщить модератору
     Re: Как работает IF UPDATE(column_name) в триггере, если изменили несколько строк?  [new]
    Kairat V. Beysenov
    Member

    Откуда: Astana City
    Сообщений: 21
    Шыфл, спс за ответ! Будем думать как переделать работу с данными в нашей системе.

    Ну а если все-таки не получится обработать данные как одно целое и придется пробегать каждую строку отдельно, что лучше выбрать курсоры или временную таблицу с int-овым идентификатором для цикла? При условии что в таблице inserted и deleted будет максимум 50 записей и в 90% случаях там будет всегда одна запись.
    10 авг 11, 07:37    [11094959]     Ответить | Цитировать Сообщить модератору
    Все форумы / Microsoft SQL Server Ответить