J'ai une table avec 42 colonnes et un déclencheur qui devrait faire des choses lorsque 38 de ces colonnes sont mises à jour. Donc, je dois ignorer la logique si les 4 autres colonnes sont modifiées.
Je peux utiliser la fonction UPDATE () et créer une grande IF
condition, mais je préfère faire quelque chose de plus court. Utilisation de COLUMNS_UPDATED Je peux vérifier si toutes certaines colonnes sont mises à jour?
Par exemple, vérifier si les colonnes 3, 5 et 9 sont mises à jour:
IF
(
(SUBSTRING(COLUMNS_UPDATED(),1,1) & 20 = 20)
AND
(SUBSTRING(COLUMNS_UPDATED(),2,1) & 1 = 1)
)
PRINT 'Columns 3, 5 and 9 updated';
Donc, valeur 20
pour la colonne 3
et 5
, et valeur 1
pour la colonne 9
car elle est définie dans le premier bit du deuxième octet. Si je change l'instruction, OR
elle vérifiera si les colonnes 3
et / 5
ou la colonne 9
est / sont mises à jour?
Comment appliquer la OR
logique dans le contexte d'un octet?
la source
SET
liste ou si les valeurs ont réellement changé? Les deuxUPDATE
etCOLUMNS_UPDATED()
seulement vous dire l'ancien. Si vous voulez savoir si les valeurs ont réellement changé, vous devrez comparer correctementinserted
et etdeleted
.SUBSTRING
pour fractionner la valeur renvoyéeCOLUMNS_UPDATED()
, vous devez utiliser une comparaison au niveau du bit, comme indiqué dans la documentation . Sachez que si vous modifiez la table de quelque manière que ce soit, l'ordre des valeurs renvoyées parCOLUMNS_UPDATED()
changera.SET
orUPDATE
, vous pouvez envisager d'utiliser à l'aide deCHECKSUM()
ouBINARY_CHECKSUM()
, ou mêmeHASHBYTES()
sur les colonnes en question.Réponses:
Vous pouvez utiliser
CHECKSUM()
une méthodologie assez simple pour comparer les valeurs réelles pour voir si elles ont été modifiées.CHECKSUM()
générera une somme de contrôle sur une liste de valeurs transmises, dont le nombre et le type sont indéterminés. Attention, il y a une petite chance de comparer des sommes de contrôle comme celle-ci entraînera de faux négatifs. Si vous ne pouvez pas gérer cela, vous pouvez utiliser à laHASHBYTES
place 1 .L'exemple ci-dessous utilise un
AFTER UPDATE
déclencheur pour conserver un historique des modifications apportées à laTriggerTest
table uniquement si l'une des valeurs des colonnesData1
ouData2
change. En cas deData3
changement, aucune action n'est entreprise.Si vous insistez pour utiliser la fonction COLUMNS_UPDATED () , vous ne devez pas coder en dur la valeur ordinale des colonnes en question, car la définition de la table peut changer, ce qui peut invalider les valeurs codées en dur. Vous pouvez calculer quelle devrait être la valeur lors de l'exécution à l'aide des tables système. N'oubliez pas que la
COLUMNS_UPDATED()
fonction renvoie true pour le bit de colonne donné si la colonne est modifiée dans N'IMPORTE QUELLE ligne affectée par l'UPDATE TABLE
instruction.Cette démo insère des lignes dans la table d'historique qui ne devraient peut-être pas être insérées. Les lignes ont vu leur
Data1
colonne mise à jour pour certaines lignes et laData3
colonne a été mise à jour pour certaines lignes. Puisqu'il s'agit d'une instruction unique, toutes les lignes sont traitées par un seul passage à travers le déclencheur. Étant donné que certaines lignes ont étéData1
mises à jour, ce qui fait partie de laCOLUMNS_UPDATED()
comparaison, toutes les lignes vues par le déclencheur sont insérées dans leTriggerHistory
tableau. Si cela est "incorrect" pour votre scénario, vous devrez peut-être gérer chaque ligne séparément, à l'aide d'un curseur.Le
TriggerResult
tableau a maintenant des lignes potentiellement trompeuses qui semblent n'appartenir à aucun, car elles ne montrent absolument aucun changement (aux deux colonnes de ce tableau). Dans le 2e ensemble de lignes de l'image ci-dessous, TriggerTestID 7 est le seul qui semble avoir été modifié. Les autres lignes n'avaient que laData3
colonne mise à jour; cependant, comme une ligne du lot a étéData1
mise à jour, toutes les lignes sont insérées dans leTriggerResult
tableau.Alternativement, comme @AaronBertrand et @srutzky l'ont souligné, vous pouvez effectuer une comparaison des données réelles dans les tables virtuelles
inserted
etdeleted
. Étant donné que la structure des deux tables est identique, vous pouvez utiliser uneEXCEPT
clause dans le déclencheur pour capturer les lignes où les colonnes précises qui vous intéressent ont changé:1 - voir /programming/297960/hash-collision-what-are-the-chances pour une discussion sur les chances infiniment faibles que le calcul HASHBYTES puisse également entraîner des collisions. Preshing a également une analyse décente de ce problème.
la source
HASHBYTES
place." est trompeur. Il est vrai qu'ilHASHBYTES
est moins susceptible d'avoir de faux négatifs queCHECKSUM
(probabilité variant selon la taille de l'algorithme utilisé), mais cela ne peut être exclu. Toute fonction de hachage aura toujours le potentiel d'avoir des collisions car il est fort probable qu'il s'agisse d'informations réduites. La seule façon d'être certain d' aucun changement est de comparer lesINSERTED
etDELETED
tables, et en utilisant une_BIN2
collation , si les données de chaîne. La comparaison des hachages ne donne qu'une certitude quant aux différences.