Ich arbeite an SQL Server 2008 R2.
Ich habe eine Tabelle Vorteil , die eine AFTER INSERT, UPDATE - Trigger genannt hat tiu_benefit .
Ich möchte eine UPDATE-Anweisung für diese Tabelle schreiben, um 1 Zeile zu aktualisieren, aber ich möchte nicht, dass der Trigger ausgelöst wird. Ich weiß, dass ich den Trigger vor UPDATE deaktivieren und anschließend nach UPDATE aktivieren kann:
DISABLE TRIGGER tiu_benefit ON benefit;
GO
UPDATE benefit SET editor = 'srh' where benefit_id = 9876
GO
ENABLE TRIGGER tiu_benefit ON benefit;
GO
Dieser Auslöser zum Deaktivieren und Aktivieren wirkt sich jedoch auf alle derzeit angemeldeten Benutzer aus. Es besteht also die Möglichkeit, dass ein anderer Benutzer ein UPDATE / INSERT ausführt, während der Trigger von meinem Skript deaktiviert wird, was nicht gut ist. Deshalb möchte ich nur den Trigger für meine aktuelle Sitzung deaktivieren und aktivieren. Ist es möglich? Wenn ja, bitte erläutern Sie wie.
Vielen Dank
Antworten:
Ich habe einige Tests durchgeführt, und ich denke, es wäre in Ordnung, wenn Sie Ihren Prozess in einer einzigen Transaktion ausführen.
In meinen Tests habe ich nur das
BEGIN TRANSACTION
und dasDISABLE TRIGGER
erste hervorgehoben und ausgeführt . Ich habe dann ein neues (zweiten) Abfrage - Fenster geöffnet und versuchte , verschiedene DML - Anweisungen (laufenSELECT
,INSERT
,UPDATE
DELETE
) gegen die Basistabelle. Alle Versuche, im zweiten Abfragefenster auf die Basistabelle zuzugreifen, haben auf die Sperren gewartet, die das Fenster mit der expliziten Transaktion hält. Nachdem ich meine explizite Transaktion festgeschrieben (oder zurückgesetzt) hatte, konnte das zweite Fenster auf die Tabelle zugreifen.quelle
benefit_id
:)Um Ihr Problem zu lösen, müssen wir programmatisch vorgehen. Es gibt zwei Routen, die Sie hier gehen können. Der Grund für die Notwendigkeit dieser Ansätze besteht darin, dass Sie einen Trigger für eine bestimmte Anweisung nicht deaktivieren können. Er kann nur für die gesamte Tabelle deaktiviert werden.
Option 1: Context_Info ()
Samuel Vanga bei MS SQL Tips hatte ein großartiges Beispiel:
Wenn Samuel nicht möchte, dass der Trigger ausgeführt wird, verwenden sie Folgendes:
Context_Info
verwendet die folgenden Systemansichten, um Informationen zur aktuellen Sitzung abzurufen:sys.dm_exec_requests
sys.dm_exec_sessions
sys.sysprocesses
Die Ideologie hier ist, dass die von Ihnen festgelegte Binärzeichenfolge nur für die aktuelle Sitzung verfügbar ist. Wenn der Trigger also während Ihrer Sitzung ausgeführt wird, wird der Gültigkeitsbereich und die variable Einstellung der
Context_info
Funktion angezeigt und es wird zum Escape-Teil des Triggers gesprungen stattdessen.Option 2: Temp-Tabelle
Itzik Ben-Gan hat eine großartige Lösung in seinem Buch "Innerhalb von Microsoft SQL Server 2008 T-SQL-Programmierung: T-SQL-Programmierung", das sich auch in seinem späteren Buch T-SQL-Abfragen befindet . Das Hauptproblem bei dieser
context_info
Funktion ist der geringe TempDB-Overhead.Um die Überraschung zu verderben, aber die Handlung der Bücher nicht zu ruinieren (ich hatte das Gefühl, dass es sich lohnt, sie zu kaufen und zu lesen), werden Sie Ihren Auslöser ändern.
Ihr Trigger sollte eine Prüfung für eine temporäre Tabelle durchführen. Wenn die temporäre Tabelle vorhanden ist, sollte der Trigger wissen, dass er die Aktionen beendet und nicht ausführt.
Erstellen Sie in der Update-Anweisung, die Sie ausführen möchten, zuerst die temporäre Tabelle. Es wird in derselben Transaktion wie der Trigger angezeigt und bewirkt, dass der Trigger Ihre Anweisung ignoriert.
Beispiel eines Triggers:
Beispiel für eine beginnende Anweisung, wenn der Trigger nicht ausgeführt werden soll:
Putting es insgesamt für Ihr Beispiel:
quelle
context_info
mitoriginal_login()
der Sie festlegen, dass der Auslöser niemals ausgeführt werden soll, wenn eine bestimmte Person den Auslöser betätigt.Ich würde entweder das
CONTEXT_INFO
oder das neuere verwendenSESSION_CONTEXT
. Beide sind sitzungsbasierte Werte.CONTEXT_INFO
ist ein einzelnerVARBINARY(128)
Wert. Dies ist seit mindestens SQL Server 2000 verfügbar. Es kannCONTEXT_INFO
von allen Benutzern angezeigt werden,VIEW SERVER STATE
da es sich um ein von dersys.dm_exec_sessions
DMV zurückgegebenes Feld handelt . Ich habe dieses schon einmal benutzt und es funktioniert ganz gut.Über SET CONTEXT_INFO setzen
Über CONTEXT_INFO () oder sys.dm_exec_sessions holen
Abhängig von der Art des Werts, in dem Sie speichern
CONTEXT_INFO
, sind einige Nuancen zu beachten. Ich beschreibe das in folgendem Blogbeitrag:Warum gibt CONTEXT_INFO () den von SET CONTEXT_INFO festgelegten exakten Wert nicht zurück?
Sitzungskontext ist ein Schlüssel / Wert-Paar von
SQL_VARIANT
Werten. Dies wurde in SQL Server 2016 eingeführt. Die Trennung von Werten für verschiedene Zwecke ist ganz nett. Der Sitzungskontext kann nur von der aktuellen Sitzung angezeigt werden.Diesen Wert über sp_set_session_context setzen
Diesen Wert über SESSION_CONTEXT holen
Eine Sache, die bezüglich der lokalen temporären Tabellenoption und sogar der Option zum Deaktivieren / Aktivieren des Auslösers beachtet werden muss: Beide erfordern eine gewisse Menge an Sperr- und Übertragungsaktivität. Beide Optionen erhöhen das Konfliktpotential, wenn auch nur geringfügig. Die beiden "Kontext" -Optionen sollten leichter sein / nur Speicher enthalten.
quelle