Ich muss einen Insert, Update Trigger in Tabelle A schreiben, der alle Zeilen aus Tabelle B löscht, deren eine Spalte (z. B. Desc) Werte wie den Wert enthält, der in die Spalte von Tabelle A eingefügt / aktualisiert wurde (z. B. Col1). Wie würde ich es schreiben, damit ich sowohl Update- als auch Insert-Fälle behandeln kann? Wie würde ich feststellen, ob der Trigger für eine Aktualisierung oder Einfügung ausgeführt wird?
quelle
quelle
Viele dieser Vorschläge werden nicht berücksichtigt, wenn Sie eine Löschanweisung ausführen, die nichts löscht.
Angenommen, Sie versuchen zu löschen, wenn eine ID einem Wert entspricht, der in der Tabelle nicht vorhanden ist.
Ihr Trigger wird immer noch aufgerufen, aber die gelöschten oder eingefügten Tabellen enthalten nichts.
Verwenden Sie dies, um sicher zu gehen:
Besonderer Dank geht an @KenDog und @Net_Prog für ihre Antworten.
Ich habe das aus ihren Skripten erstellt.
quelle
Ich verwende Folgendes, es erkennt auch korrekt Löschanweisungen, die nichts löschen:
quelle
Nach langem Suchen konnte ich kein genaues Beispiel für einen einzelnen SQL Server-Trigger finden, der alle (3) drei Bedingungen der Triggeraktionen INSERT, UPDATE und DELETE behandelt. Ich habe endlich eine Textzeile gefunden, die darüber sprach, dass die gemeinsame Tabelle DELETED einen Datensatz für diese beiden Aktionen enthält, wenn ein DELETE oder UPDATE auftritt. Basierend auf diesen Informationen habe ich dann eine kleine Aktionsroutine erstellt, die bestimmt, warum der Trigger aktiviert wurde. Diese Art von Schnittstelle wird manchmal benötigt, wenn sowohl eine gemeinsame Konfiguration als auch eine bestimmte Aktion für einen INSERT vs. UPDATE-Trigger ausgeführt werden. In diesen Fällen würde das Erstellen eines separaten Triggers für UPDATE und INSERT zu einem Wartungsproblem. (dh wurden beide Trigger ordnungsgemäß aktualisiert, um den erforderlichen gemeinsamen Datenalgorithmus zu beheben?)
Zu diesem Zweck möchte ich das folgende Ereigniscode-Snippet mit mehreren Triggern für die Behandlung von INSERT, UPDATE, DELETE in einem Trigger für einen Microsoft SQL Server bereitstellen.
quelle
Ich glaube verschachtelt wenn ein wenig verwirrend und:
;)
quelle
quelle
Versuche dies..
quelle
Ich mag zwar auch die Antwort von @Alex, aber ich biete diese Variante der obigen Lösung von @ Graham an
Dies verwendet ausschließlich das Vorhandensein von Datensätzen in den Tabellen INSERTED und UPDATED, im Gegensatz zur Verwendung von COLUMNS_UPDATED für den ersten Test. Es bietet dem paranoiden Programmierer auch Erleichterung, wenn er weiß, dass der endgültige Fall in Betracht gezogen wurde ...
Sie erhalten NOOP mit einer Aussage wie der folgenden:
quelle
END
falsch eingerückt ist! (verursacht zu fragen, wo die ersteBEGIN
geschlossen ist)Dies könnte ein schnellerer Weg sein:
quelle
Ein potenzielles Problem bei den beiden angebotenen Lösungen besteht darin, dass eine Aktualisierungsabfrage je nach Schreibweise möglicherweise keine Datensätze aktualisiert und eine Einfügeabfrage möglicherweise keine Datensätze einfügt. In diesen Fällen sind die eingefügten und gelöschten Datensatzgruppen leer. In vielen Fällen, wenn sowohl die eingefügten als auch die gelöschten Datensätze leer sind, möchten Sie den Trigger möglicherweise nur beenden, ohne etwas zu tun.
quelle
Ich habe einen kleinen Fehler in Grahams ansonsten cooler Lösung gefunden:
Es sollte IF COLUMNS_UPDATED () < > 0 sein - Einfügen oder Aktualisieren
anstelle von> 0, wahrscheinlich weil das oberste Bit als SIGNED Integer Sign Bit interpretiert wird ... (?). Also insgesamt:
quelle
Das macht den Trick für mich:
Da nicht alle Spalten gleichzeitig aktualisiert werden können, können Sie überprüfen, ob eine bestimmte Spalte folgendermaßen aktualisiert wird:
quelle
quelle
Ich mag Lösungen, die "Informatik elegant" sind. Meine Lösung hier trifft die Pseudotabellen [eingefügt] und [gelöscht] jeweils einmal, um ihren Status zu erhalten, und fügt das Ergebnis in eine Bitmap-Variable ein. Dann kann jede mögliche Kombination von INSERT, UPDATE und DELETE während des gesamten Triggers mit effizienten binären Auswertungen leicht getestet werden (mit Ausnahme der unwahrscheinlichen Kombination INSERT oder DELETE).
Es wird davon ausgegangen, dass es keine Rolle spielt, wie die DML-Anweisung lautete, wenn keine Zeilen geändert wurden (was die überwiegende Mehrheit der Fälle erfüllen sollte). Es ist zwar nicht so vollständig wie die Lösung von Roman Pekar, aber effizienter.
Mit diesem Ansatz haben wir die Möglichkeit, einen "FOR INSERT, UPDATE, DELETE" -Trigger pro Tabelle zu verwenden, wodurch wir A) die vollständige Kontrolle über die Aktionsreihenfolge und b) eine Codeimplementierung pro für mehrere Aktionen anwendbarer Aktion erhalten. (Natürlich hat jedes Implementierungsmodell seine Vor- und Nachteile. Sie müssen Ihre Systeme individuell bewerten, um herauszufinden, was wirklich am besten funktioniert.)
Beachten Sie, dass die Anweisungen "existiert (wählen Sie * aus" eingefügt / gelöscht ")" sehr effizient sind, da kein Festplattenzugriff besteht ( https://social.msdn.microsoft.com/Forums/en-US/01744422-23fe-42f6) -9ab0-a255cdf2904a ).
quelle
Schnelle Lösung MySQL
Übrigens: Ich benutze MySQL PDO.
(1) In einer Tabelle mit automatischem Inkrementieren erhalten Sie einfach den höchsten Wert (mein Spaltenname = ID) aus der inkrementierten Spalte, sobald jedes Skript zuerst ausgeführt wird:
(2) Führen Sie die MySQL-Abfrage wie gewohnt aus und wandeln Sie das Ergebnis in eine Ganzzahl um, z.
(3) Nach der Abfrage "INSERT IN ... ON DUPLICATE KEY UPDATE" erhalten Sie die zuletzt eingefügte ID auf Ihre bevorzugte Weise, z.
(4) Vergleichen und reagieren: Wenn die lastInsertId höher als die höchste in der Tabelle ist, handelt es sich wahrscheinlich um eine INSERT, oder? Und umgekehrt.
Ich weiß, dass es schnell und vielleicht schmutzig ist. Und es ist ein alter Beitrag. Aber hey, ich habe lange nach einer Lösung gesucht, und vielleicht findet jemand meinen Weg trotzdem etwas nützlich. Alles Gute!
quelle
einfach so
quelle
Im ersten Szenario habe ich angenommen, dass Ihre Tabelle die Spalte IDENTITY hat
Im zweiten Szenario muss die Spalte IDENTITTY nicht verwendet werden
quelle
WENN seine Aktualisierung
wenn seine Einfügung
quelle
Ich habe diese
exists (select * from inserted/deleted)
Abfragen schon lange verwendet, aber es reicht immer noch nicht für leere CRUD-Operationen (wenn keine Datensätzeinserted
unddeleted
Tabellen vorhanden sind). Nachdem ich mich ein wenig mit diesem Thema befasst habe, habe ich eine genauere Lösung gefunden:Es ist auch möglich zu
columns_updated() & power(2, column_id - 1) > 0
sehen, ob die Spalte aktualisiert wird, aber es ist nicht sicher für Tabellen mit einer großen Anzahl von Spalten. Ich habe eine etwas komplexe Berechnungsmethode verwendet (siehe hilfreichen Artikel unten).Außerdem klassifiziert dieser Ansatz einige Aktualisierungen immer noch fälschlicherweise als Einfügungen (wenn jede Spalte in der Tabelle von Aktualisierungen betroffen ist), und klassifiziert wahrscheinlich Einfügungen, bei denen nur Standardwerte als Löschungen eingefügt werden, diese jedoch König seltener Operationen sind (at Leasing in meinem System sind sie). Außerdem weiß ich derzeit nicht, wie ich diese Lösung verbessern kann.
quelle
quelle
Ich mache das:
1 -> einfügen
2 -> löschen
3 -> aktualisieren
quelle
quelle