Eu tenho uma tabela com 42 colunas e um gatilho que deve fazer algumas coisas quando 38 dessas colunas forem atualizadas. Então, preciso pular a lógica se as 4 colunas restantes forem alteradas.
Eu posso usar a função UPDATE() e criar uma grande IF
condição, mas prefiro fazer algo mais curto. Usando COLUMNS_UPDATED posso verificar se todas as colunas estão atualizadas?
Por exemplo, verificando se as colunas 3, 5 e 9 estão atualizadas:
IF
(
(SUBSTRING(COLUMNS_UPDATED(),1,1) & 20 = 20)
AND
(SUBSTRING(COLUMNS_UPDATED(),2,1) & 1 = 1)
)
PRINT 'Columns 3, 5 and 9 updated';
Portanto, valor 20
para coluna 3
e 5
, e valor 1
para coluna 9
porque está definido no primeiro bit do segundo byte. Se eu alterar a instrução para OR
ela, verificará se as colunas 3
e / 5
ou coluna 9
estão/estão atualizadas?
Como pode aplicar OR
a lógica no contexto de um byte?
Você pode usar
CHECKSUM()
como uma metodologia bastante simples para comparar valores reais para ver se eles foram alterados.CHECKSUM()
irá gerar uma soma de verificação em uma lista de valores passados, cujo número e tipo são indeterminados. Cuidado, há uma pequena chance de comparar somas de verificação como essa resultar em falsos negativos. Se você não pode lidar com isso, você podeHASHBYTES
usar 1 .O exemplo abaixo usa um
AFTER UPDATE
gatilho para reter um histórico de modificações feitas naTriggerTest
tabela somente se um dos valores nas colunasData1
ou for alterado.Data2
Se houverData3
alterações, nenhuma ação será tomada.Se você insistir em usar a função COLUMNS_UPDATED() , você não deve codificar o valor ordinal das colunas em questão, pois a definição da tabela pode mudar, o que pode invalidar os valores codificados. Você pode calcular qual deve ser o valor em tempo de execução usando as tabelas do sistema. Esteja ciente de que a
COLUMNS_UPDATED()
função retorna true para o bit de coluna fornecido se a coluna for modificada em QUALQUER linha afetada pelaUPDATE TABLE
instrução.Esta demonstração insere linhas na tabela de histórico que talvez não devam ser inseridas. As linhas tiveram sua
Data1
coluna atualizada para algumas linhas e tiveram aData3
coluna atualizada para algumas linhas. Como esta é uma única instrução, todas as linhas são processadas por uma única passagem pelo gatilho. Como algumas linhas foramData1
atualizadas, o que faz parte daCOLUMNS_UPDATED()
comparação, todas as linhas vistas pelo gatilho são inseridas naTriggerHistory
tabela. Se isso for "incorreto" para seu cenário, talvez seja necessário manipular cada linha separadamente, usando um cursor.A
TriggerResult
tabela agora tem algumas linhas potencialmente enganosas que parecem não pertencer, pois não mostram absolutamente nenhuma alteração (nas duas colunas dessa tabela). No 2º conjunto de linhas na imagem abaixo, o TriggerTestID 7 é o único que parece ter sido modificado. As demais linhas tiveram apenas aData3
coluna atualizada; no entanto, como uma linha do lote foiData1
atualizada, todas as linhas são inseridas naTriggerResult
tabela.Como alternativa, como @AaronBertrand e @srutzky apontaram, você pode realizar uma comparação dos dados reais nas tabelas
inserted
e nasdeleted
tabelas virtuais. Como a estrutura de ambas as tabelas é idêntica, você pode usar umaEXCEPT
cláusula no gatilho para capturar linhas em que as colunas precisas em que você está interessado foram alteradas:1 - veja https://stackoverflow.com/questions/297960/hash-collision-what-are-the-chances para uma discussão sobre a pequena chance de que o cálculo de HASHBYTES também possa resultar em colisões. Preshing também tem uma análise decente desse problema.