Определить строку как имеющую изменения, исключая изменения в определенных столбцах - PullRequest
2 голосов
/ 23 февраля 2011

В рамках наших бизнес-правил нам необходимо отслеживать, когда строка обозначена как измененная.Таблица содержит несколько столбцов, обозначенных как неактуальные для наших бизнес-целей (например, поле ввода даты, отметка времени, поле проверенного бита или поле полученного бита).В таблице много столбцов, и я пытаюсь найти элегантный способ определить, изменилось ли какое-либо из соответствующих полей, и затем записать запись в таблицу аудита (ввод значения PK строки - PK не может быть отредактирован).Мне даже не нужно знать, какой столбец действительно изменился (хотя это было бы неплохо в будущем).

Я могу выполнить это с помощью хранимой процедуры, но это уродливый SP, использующий следующий синтаксисдля обновления (операторы OR значительно укорочены для записи):

INSERT INTO [TblSourceDataChange] (pkValue)
    SELECT d.pkValue
    FROM deleted d INNER JOIN inserted i ON d.pkValue=i.pkValue
    WHERE (    i.[F440] <> d.[F440]
          OR i.[F445] <> d.[F445]
          OR i.[F450] <> d.[F450])

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

Ответы [ 4 ]

1 голос
/ 24 февраля 2011

Я возражаю!Одно слово, которое я не могу использовать, чтобы описать доступную опцию, элегантно.Я еще не нашел удовлетворительный способ выполнить то, что вы хотите.Есть варианты, но все они чувствуют себя немного неудовлетворительно.Когда / почему вы выбрали эти параметры, зависит от некоторых факторов, которые вы не упомянули.

  • Как часто вам нужно «спрашивать», какие поля изменились?то есть пользователи редко переходят по ссылке "история аудита"?Или это все время, чтобы разобраться, как должно работать ваше приложение?
  • Сколько стоит дисковое пространство?Я не обманываю, но я работал в местах, где стратегия хранения для нашего аудита была вопросом на миллион долларов, исходя из того, что нам платили за место в санатории.размер был.Вы можете быть тем же или наоборот.

Изменить захват данных

Как уже упоминалось @TGnat, вы можете использовать CDC.Этот метод хорош тем, что вы просто включаете отслеживание изменений, а затем вызываете sproc для начала отслеживания.CDC хорош, потому что это довольно эффективное хранилище и разумная мощность.Вы также устанавливаете это и забываете это, то есть, пока разработчики не придут и не захотят изменить форму ваших таблиц.Для здравомыслия разработчика вам нужно сгенерировать скрипт, который отключает / включает отслеживание для ваших сущностей.

Я заметил, что вы хотите исключить определенные столбцы, а не включить их.Вы можете сделать это с помощью трюка FOR XML PATH.Вы можете написать запрос наподобие следующего, а затем использовать переменную @capturedColList при вызове sys.sp_cdc_enable_table ..

 SET @capturedColList =   SELECT Substring( (
                SELECT ',' + COLUMN_Name
                FROM INFORMATION_SCHEMA.COLUMNS 
                WHERE TABLE_NAME = '<YOUR_TABLE>' AND
                      COLUMN_NAME NOT IN ('excludedA', 'excludedB')

                FOR XML PATH( '' )  
            )  , 2, 8000)

Триггеры со случаями Второй вариант, который я вижу, заключается весть какая-то генерация кода.Это может быть внешний жгут или SPROC, который записывает ваши триггеры.Каким бы ни был ваш яд, он должен быть автоматизированным и универсальным.Но вы будете в основном писать код, который записывает DDL для триггеров, которые сравнивают ток с INSERTED или DELETED, используя тонны несвойственных операторов CASE для каждого столбца.

Здесь обсуждается стиль здесь .

Записать все, потом разобраться

Последний вариант - использовать триггер для записи каждого изменения строки.Затем вы пишете код (SPROCS / UDF), который может просматривать ваши данные журнала и распознавать, когда произошли изменения.Почему вы выбрали бы этот вариант?Дисковое пространство не имеет значения, и хотя вам необходимо уметь понимать, что изменилось, вы лишь редко задаете системе этот вопрос.

HTH,

-eric

1 голос
/ 23 февраля 2011

Взгляните на Изменить захват данных . Это новая функция в SQL Server 2008.

Сначала Вы включаете CDC в базе данных:

EXEC sys.sp_cdc_enable_db

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

EXEC sys.sp_cdc_enable_table
    @source_schema = 'dbo',
    @source_name = 'xxx',
    @supports_net_changes = 1,
    @role_name = NULL, 
    @captured_column_list = N'xxx1,xxx2,xxx3'

Это создает таблицу изменений с именем cdc.dbo_xxx. Любые изменения, внесенные в записи в таблице, записываются в эту таблицу.

0 голосов
/ 25 февраля 2011

Я нашел ответ в посте Обновление SQL Server, Получить только измененные поля и адаптировал SQL под свои нужды (этот sql находится в триггере).SQL публикуется ниже:

ОБЪЯВЛЯЕТ @idTable INT SELECT @idTable = T.id ОТ системных объектов P ПРИСОЕДИНЯЙТЕСЬ к системным объектам T ON P.parent_obj = T.id, ГДЕ P.id = @@ procid

ЕСЛИ СУЩЕСТВУЕТ (ВЫБРАТЬ * ИЗ СИСТЕМНЫХ КОЛОНК, ГДЕ id = @ idTable
И ПРЕОБРАЗОВАТЬ (VARBINARY, REVERSE (COLUMNS_UPDATED ())) & POWER (ПРЕОБРАЗОВАТЬ (BIGINT, 2), colorder - 1)> 0 И имя НЕ ВХОДИТ ('отметка времени ',' Отзыв ')) НАЧАЛО - Делайте соответствующие вещи здесь END

0 голосов
/ 23 февраля 2011

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

...