Eu tenho tabela com 42 colunas e um gatilho que deve fazer algumas coisas quando 38 dessas colunas são atualizadas. Então, eu preciso pular a lógica se as 4 colunas restantes forem alteradas.
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 sã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
pois é definido no primeiro bit do segundo byte. Se eu alterar a instrução, OR
ela verificará se as colunas 3
e / 5
ou a coluna 9
estão atualizadas?
Como aplicar a OR
lógica no contexto de um byte?
sql-server
t-sql
trigger
gotqn
fonte
fonte
SET
lista ou se os valores realmente foram alterados? AmbosUPDATE
eCOLUMNS_UPDATED()
apenas lhe dizem o primeiro. Se você quiser saber se os valores realmente mudaram, será necessário fazer uma comparação adequada deinserted
edeleted
.SUBSTRING
para dividir o formulário retornado pelo valorCOLUMNS_UPDATED()
, você deve usar uma comparação bit a bit, conforme mostrado na documentação . Lembre-se de que, se você alterar a tabela de alguma forma, a ordem dos valores retornados porCOLUMNS_UPDATED()
será alterada.SET
ouUPDATE
, convém usarCHECKSUM()
ouBINARY_CHECKSUM()
, ou mesmoHASHBYTES()
sobre as colunas em questão.Respostas:
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, dos quais o número e o tipo são indeterminados. Cuidado, há uma pequena chance de comparar somas de verificação como essa, resultando em falsos negativos. Se você não consegue lidar com isso, você pode usarHASHBYTES
em vez de 1 .O exemplo abaixo usa um
AFTER UPDATE
gatilho para manter um histórico de modificações feitas naTriggerTest
tabela somente se um dos valores nas colunasData1
ou forData2
alterado. Se forData3
alterado, nenhuma ação será tomada.Se você insistir em usar a função COLUMNS_UPDATED () , não deverá 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 retornará true para o bit especificado da coluna 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 aData3
coluna atualizada para algumas linhas. Como essa é uma instrução única, 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 acionador são inseridas naTriggerHistory
tabela. Se isso estiver "incorreto" para o seu cenário, talvez você precise 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 segundo conjunto de linhas da imagem abaixo, o TriggerTestID 7 é o único que parece ter sido modificado. As outras linhas apenas tiveram aData3
coluna atualizada; no entanto desde a uma linha no lote tinhaData1
atualizado, todas as linhas são inseridas naTriggerResult
tabela.Como alternativa, como apontaram @AaronBertrand e @srutzky, é possível realizar uma comparação dos dados reais nas tabelas
inserted
edeleted
virtual. Como a estrutura de ambas as tabelas é idêntica, você pode usar umaEXCEPT
cláusula no gatilho para capturar linhas nas quais as colunas precisas em que você está interessado foram alteradas:1 - consulte /programming/297960/hash-collision-what-are-the-chances para uma discussão da pequena chance de que o cálculo do HASHBYTES também possa resultar em colisões. Preshing também tem uma análise decente desse problema.
fonte
HASHBYTES
". é enganoso. É verdade queHASHBYTES
é menos provável que haja um falso negativo do queCHECKSUM
(probabilidade que varia no tamanho do algoritmo usado), mas não pode ser descartado. Qualquer função de hash sempre terá o potencial de ter colisões, pois é provável que haja informações reduzidas. A única maneira de ter certeza de nenhuma mudança é comparar osINSERTED
eDELETED
tabelas, e usando um_BIN2
agrupamento se for dados de cadeia. Comparar hashes apenas garante segurança para as diferenças.