У меня есть таблица с 42 столбцами и триггер, который должен делать некоторые вещи, когда 38 из этих столбцов обновляются. Итак, мне нужно пропустить логику, если остальные 4 столбца изменены.
Я могу использовать функцию UPDATE () и создать одно большое IF
условие, но предпочитаю делать что-то более короткое. Используя COLUMNS_UPDATED, я могу проверить, все ли определенные столбцы обновлены?
Например, проверка обновления столбцов 3, 5 и 9:
IF
(
(SUBSTRING(COLUMNS_UPDATED(),1,1) & 20 = 20)
AND
(SUBSTRING(COLUMNS_UPDATED(),2,1) & 1 = 1)
)
PRINT 'Columns 3, 5 and 9 updated';
Итак, значение 20
для столбца 3
и 5
, и значение 1
для столбца, 9
потому что оно установлено в первом бите второго байта. Если я изменю утверждение, OR
оно будет проверять , обновляются ли столбцы 3
и / 5
или столбец 9
?
Как можно применить OR
логику в контексте одного байта?
sql-server
t-sql
trigger
gotqn
источник
источник
SET
списке, или значения действительно изменились? И тоUPDATE
и другоеCOLUMNS_UPDATED()
скажу только первое. Если вы хотите узнать, изменились ли значения на самом деле, вам нужно сделать правильное сравнениеinserted
иdeleted
.SUBSTRING
чтобы использовать для разделения значения, возвращаемого формойCOLUMNS_UPDATED()
, вы должны использовать побитовое сравнение, как показано в документации . Помните, что если вы измените таблицу каким-либо образом,COLUMNS_UPDATED()
изменится порядок значений, возвращаемых .SET
илиUPDATE
, вы можете захотеть посмотреть на использованиеCHECKSUM()
илиBINARY_CHECKSUM()
, или дажеHASHBYTES()
на рассматриваемые столбцы.Ответы:
Вы можете использовать
CHECKSUM()
в качестве довольно простой методологии для сравнения фактических значений, чтобы увидеть, были ли они изменены.CHECKSUM()
сгенерирует контрольную сумму по списку переданных значений, число и тип которых не определены. Осторожно, есть небольшой шанс, что сравнение контрольных сумм приведет к ложным отрицаниям. Если вы не можете справиться с этим, вы можете использоватьHASHBYTES
вместо 1 .В приведенном ниже примере используется
AFTER UPDATE
триггер для сохранения истории изменений, внесенных вTriggerTest
таблицу, только при изменении любого из значений в столбцахData1
илиData2
. ЕслиData3
изменения, никаких действий не предпринимается.Если вы настаиваете на использовании функции COLUMNS_UPDATED () , вам не следует жестко кодировать порядковый номер рассматриваемых столбцов, так как определение таблицы может измениться, что может сделать недействительными жестко закодированные значения. Вы можете рассчитать, какое значение должно быть во время выполнения, используя системные таблицы. Имейте в виду, что
COLUMNS_UPDATED()
функция возвращает истину для заданного бита столбца, если столбец изменен в ЛЮБОЙ строке, затронутойUPDATE TABLE
оператором.Эта демонстрация вставляет в таблицу истории строки, которые, возможно, не следует вставлять. Столбцы
Data1
обновили свой столбец для некоторых строк, аData3
столбец обновили для некоторых строк. Поскольку это один оператор, все строки обрабатываются за один проход через триггер. Поскольку некоторые строкиData1
обновлены, что является частьюCOLUMNS_UPDATED()
сравнения, все строки, видимые триггером, вставляются вTriggerHistory
таблицу. Если это «неверно» для вашего сценария, вам может потребоваться обрабатывать каждую строку отдельно, используя курсор.В
TriggerResult
таблице теперь есть некоторые потенциально вводящие в заблуждение строки, которые выглядят так, как будто они не принадлежат, поскольку они не показывают абсолютно никаких изменений (для двух столбцов в этой таблице). Во втором наборе строк на изображении ниже TriggerTestID 7 - единственный, который выглядит так, как будто он был изменен. В других строках толькоData3
столбец обновлялся; однако, поскольку одна строка в пакетеData1
обновлена, все строки вставляются вTriggerResult
таблицу.Альтернативно, как @AaronBertrand и @srutzky отметили, вы можете выполнить сравнение фактических данных в
inserted
иdeleted
виртуальных таблицах. Поскольку структура обеих таблиц идентична, вы можете использоватьEXCEPT
предложение в триггере для захвата строк, в которых изменились интересующие вас столбцы:1 - см. Https://stackoverflow.com/questions/297960/hash-collision-what-are-the-chances, чтобы обсудить маловероятную вероятность того, что расчет HASHBYTES также может привести к коллизиям. У Прешинга также есть приличный анализ этой проблемы.
источник
HASHBYTES
вместо этого». вводит в заблуждение. Это правда , чтоHASHBYTES
это менее вероятно , чтобы иметь ложные негативы , чемCHECKSUM
(правдоподобия варьирования по размеру используемого алгоритма), но она не может быть исключена. Любая хеширующая функция всегда может иметь коллизии, поскольку вполне вероятно, что информация будет сокращена. Единственный способ быть уверенным в каких - либо изменений , чтобы сравнитьINSERTED
иDELETED
таблиц, а также с помощью_BIN2
сортировки , если это строка данных. Сравнение хэшей только дает уверенность в различиях.