2010-07-10 3 views
4

У меня есть триггер после сборки SQLCCR. Внутри этого я хотел бы знать, какие столбцы были действительно обновлены (и их значения были изменены).Я хотел бы знать, какие столбцы были ДЕЙСТВИТЕЛЬНО изменены

К сожалению, SqlContext.TriggerContext.IsUpdatedColumn возвращает true, даже если значение столбца остается неизменным. Я думаю, это связано с тем, что SQL-запрос, подготовленный не очень-умным серверным приложением, переписывает все столбцы, даже если некоторые из них не были изменены пользователем.

Вторая проблема заключается в том, что некоторые из столбцов имеют тип ntext, поэтому я не могу даже выбрать их из псевдослучайной таблицы INSERTED (MS SQL Server не разрешает поля SELECT, которые имеют тип ntext от INSERTED). Вот почему сейчас я ВЫБРАТЬ изменил строки со следующим запросом:

SELECT * FROM [dbo].[MyTable] WHERE [id] IN (SELECT [id] FROM INSERTED) 

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

Теперь у меня есть простая идея: создать еще один триггер, ПЕРЕД и сохранить обновленные строки изнутри. Затем, когда выполняется триггер AFTER, сравните значения столбца. Является ли эта идея лучшей, что я могу сделать? Если да, то в каком месте лучше хранить измененные строки между триггерами BEFORE и AFTER? Временная таблица будет удалена до запуска триггера AFTER, поскольку я закрываю контекстное соединение (возможно, просто не закрываю?).

ответ

2

ОК, теперь я решил проблему.

Прежде всего, я создал полную копию исходной таблицы (данные + структура):

IF NOT EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'copyTable') 
SELECT * INTO copyTable FROM MyTable 

Затем я сравниваю таблицу источника с его копией в начале моего триггера:

SELECT A.* FROM MyTable A, copyTable B WHERE 
    A.id IN (SELECT [id] FROM INSERTED) AND 
    A.id = B.id AND 
    A.{0} <> B.{0} 

Замените {0} нужной колонкой. Этот столбец точно соответствует столбцу, который вы должны знать, обновляется или нет. В моем случае он определяется динамически, но вы можете рассчитывать статически все столбцы, которые вам нужны.

Et voila - вы выбрали только строки, которые действительно изменены.

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

UPDATE copyTable SET 
    id = s.id, 
    col1 = s.col1, 
    ... all columns you'd like to control ... 
FROM MyTable s WHERE 
    s.id IN (SELECT [id] FROM INSERTED) AND 
    copyTable.id = s.id 

Может быть, есть лучшее решение, но это тоже работает, как хорошо.

С уважением,