Ich habe eine Tabelle mit 42 Spalten und einen Trigger, der einige Dinge tun sollte, wenn 38 dieser Spalten aktualisiert werden. Ich muss also die Logik überspringen, wenn die restlichen 4 Spalten geändert werden.
Ich kann die UPDATE () - Funktion verwenden und eine große IF
Bedingung erstellen , bevorzuge jedoch eine kürzere. Mit COLUMNS_UPDATED kann ich überprüfen, ob alle bestimmten Spalten aktualisiert wurden?
Überprüfen Sie beispielsweise, ob die Spalten 3, 5 und 9 aktualisiert wurden:
IF
(
(SUBSTRING(COLUMNS_UPDATED(),1,1) & 20 = 20)
AND
(SUBSTRING(COLUMNS_UPDATED(),2,1) & 1 = 1)
)
PRINT 'Columns 3, 5 and 9 updated';
Also Wert 20
für Spalte 3
und 5
und Wert 1
für Spalte, 9
da er im ersten Bit des zweiten Bytes gesetzt ist. Wenn ich die Anweisung in ändere, OR
wird überprüft, ob Spalten 3
und / 5
oder Spalten 9
aktualisiert werden.
Wie kann man OR
Logik im Kontext eines Bytes anwenden ?
quelle
SET
Liste aufgeführt sind oder ob sich die Werte tatsächlich geändert haben? BeidesUPDATE
undCOLUMNS_UPDATED()
nur das erstere. Wenn Sie wissen möchten, ob sich die Werte tatsächlich geändert haben, müssen Sie einen ordnungsgemäßen Vergleich voninserted
und durchführendeleted
.SUBSTRING
das zurückgegebene Wertformular zu teilenCOLUMNS_UPDATED()
, sollten Sie einen bitweisen Vergleich verwenden, wie in der Dokumentation gezeigt . Beachten Sie, dass sich die Reihenfolge der von zurückgegebenen Werte ändert, wenn Sie die Tabelle auf irgendeine WeiseCOLUMNS_UPDATED()
ändern.SET
oder -Anweisung aktualisiert wurdenUPDATE
, sollten Sie sich die Verwendung vonCHECKSUM()
oderBINARY_CHECKSUM()
oder sogarHASHBYTES()
die betreffenden Spalten ansehen .Antworten:
Sie können
CHECKSUM()
eine relativ einfache Methode zum Vergleichen der tatsächlichen Werte verwenden, um festzustellen, ob sie geändert wurden.CHECKSUM()
erzeugt eine Prüfsumme über eine Liste von übergebenen Werten, deren Anzahl und Typ unbestimmt sind. Achtung, es gibt eine kleine Chance, dass ein Vergleich von Prüfsummen zu falschen Negativen führt. Wenn Sie damit nicht umgehen können, können SieHASHBYTES
stattdessen 1 verwenden .Im folgenden Beispiel wird ein
AFTER UPDATE
Trigger verwendet, um den Verlauf der an derTriggerTest
Tabelle vorgenommenen Änderungen nur dann beizubehalten, wenn sich einer der Werte in der SpalteData1
oderData2
ändert. BeiData3
Änderungen wird keine Aktion ausgeführt.Wenn Sie darauf bestehen, die Funktion COLUMNS_UPDATED () zu verwenden , sollten Sie den Ordinalwert der betreffenden Spalten nicht hartcodieren , da sich die Tabellendefinition ändern kann, wodurch hartcodierte Werte ungültig werden können. Anhand der Systemtabellen können Sie berechnen, wie hoch der Wert zur Laufzeit sein soll. Beachten Sie, dass die
COLUMNS_UPDATED()
Funktion für die gegebene Spalte Bit true zurück , wenn die Spalte in modifiziert wird jedem der betroffenen ZeileUPDATE TABLE
Aussage.Diese Demo fügt Zeilen in die Verlaufstabelle ein, die möglicherweise nicht eingefügt werden sollten. Die Reihen haben ihre hatten
Data1
Spalte für einige Zeilen aktualisiert und haben die hattenData3
Spalte für einige Zeilen aktualisiert. Da es sich um eine einzelne Anweisung handelt, werden alle Zeilen in einem Durchgang durch den Trigger verarbeitet. Da einige ZeilenData1
aktualisiert wurden, was Teil desCOLUMNS_UPDATED()
Vergleichs ist, werden alle vom Trigger angezeigten Zeilen in dieTriggerHistory
Tabelle eingefügt . Wenn dies für Ihr Szenario "falsch" ist, müssen Sie möglicherweise jede Zeile einzeln mit einem Cursor behandeln.Die
TriggerResult
Tabelle enthält jetzt einige möglicherweise irreführende Zeilen, die so aussehen, als gehörten sie nicht dazu, da sie absolut keine Änderungen aufweisen (an den beiden Spalten in dieser Tabelle). In der zweiten Reihe von Zeilen im Bild unten ist TriggerTestID 7 die einzige, die so aussieht, als ob sie geändert wurde. In den anderen Zeilen wurde nur dieData3
Spalte aktualisiert. Da jedoch die eine Zeile im StapelData1
aktualisiert wurde, werden alle Zeilen in dieTriggerResult
Tabelle eingefügt .Alternativ können Sie, wie @AaronBertrand und @srutzky betonten, einen Vergleich der tatsächlichen Daten in der
inserted
und derdeleted
virtuellen Tabelle durchführen . Da die Struktur beider Tabellen identisch ist, können Sie eineEXCEPT
Klausel im Trigger verwenden, um Zeilen zu erfassen, in denen sich die genauen gewünschten Spalten geändert haben:1 - siehe /programming/297960/hash-collision-what-are-the-chances für eine Diskussion der verschwindend geringen Wahrscheinlichkeit, dass die HASHBYTES-Berechnung auch zu Kollisionen führen kann. Preshing hat auch eine anständige Analyse dieses Problems.
quelle
HASHBYTES
stattdessen verwenden." ist irreführend. Es ist wahr, dassHASHBYTES
es weniger wahrscheinlich ist , dass ein falsches Negativ vorliegt alsCHECKSUM
(Wahrscheinlichkeit variiert je nach Größe des verwendeten Algorithmus), aber es kann nicht ausgeschlossen werden. Jede Hash-Funktion kann immer zu Kollisionen führen, da es sich mit ziemlicher Wahrscheinlichkeit um reduzierte Informationen handelt. Der einzige Weg , um sicher zu gehen ohne Änderungen ist es, die zu vergleichenINSERTED
undDELETED
Tabellen, und mit einer_BIN2
Sortierungs wenn es String - Daten ist. Das Vergleichen von Hashes gibt nur Sicherheit für Unterschiede.