it-swarm.com.de

Gibt es eine Möglichkeit, einen SQL Server-Trigger nur für einen bestimmten Ausführungsbereich zu deaktivieren?

Gibt es in SQL Server 2005 eine Möglichkeit für einen Trigger, um herauszufinden, welches Objekt für das Auslösen des Triggers verantwortlich ist? Ich möchte dies verwenden, um den Trigger für ein gespeichertes Produkt zu deaktivieren.

Gibt es eine andere Möglichkeit, den Trigger nur für die aktuelle Transaktion zu deaktivieren? Ich könnte den folgenden Code verwenden, aber wenn ich mich nicht irre, würde dies auch gleichzeitige Transaktionen betreffen - was eine schlechte Sache wäre.

DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

Wenn möglich, möchte ich die Technik vermeiden, ein "NoTrigger" -Feld in meiner Tabelle zu haben und einen NoTrigger = null zu machen, weil ich die Tabelle so klein wie möglich halten möchte.

Der Grund, warum ich den Auslöser vermeiden möchte, ist, dass er Logik enthält, die für manuelle Aktualisierungen der Tabelle wichtig ist, aber meine gespeicherte Prozedur übernimmt diese Logik. Da dies ein häufig verwendetes Verfahren ist, möchte ich, dass es schnell ist.

Trigger verursachen zusätzlichen Overhead auf dem Server, da sie eine implizite Transaktion initiieren. Sobald ein Trigger ausgeführt wird, wird eine neue implizite Transaktion gestartet, und bei jedem Datenabruf innerhalb einer Transaktion werden die betroffenen Tabellen gesperrt.

Von: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1170220,00.html#trigger

35
Seibar

Ich habe gerade gesehen, wie dieser Artikel kürzlich im SQL Server Central-Newsletter hervorgehoben wurde, und er scheint eine Möglichkeit zu bieten, die Sie möglicherweise mithilfe der Context_Info für die Verbindung als nützlich erachten:

http://www.mssqltips.com/tip.asp?tip=1591


EDIT von Terrapin:

Der obige Link enthält den folgenden Code:

USE AdventureWorks;  
GO  
-- creating the table in AdventureWorks database  
IF OBJECT_ID('dbo.Table1') IS NOT NULL  
DROP TABLE dbo.Table1  
GO  
CREATE TABLE dbo.Table1(ID INT)  
GO   
-- Creating a trigger  
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE  
AS  
DECLARE @Cinfo VARBINARY(128)  
SELECT @Cinfo = Context_Info()  
IF @Cinfo = 0x55555  
RETURN  
PRINT 'Trigger Executed'  
-- Actual code goes here  
-- For simplicity, I did not include any code  
GO  

Wenn Sie verhindern möchten, dass der Trigger ausgeführt wird, können Sie Folgendes tun:

SET Context_Info 0x55555 
INSERT dbo.Table1 VALUES(100)
56
Cade Roux

Wenn Ihr Trigger zu Leistungsproblemen in Ihrer Anwendung führt, besteht der beste Ansatz darin, alle manuellen Aktualisierungen der Tabelle zu entfernen und alle Aktualisierungen zu erfordern, um die gespeicherten Prozeduren zum Einfügen/Aktualisieren durchzugehen, die die korrekte Aktualisierungslogik enthalten. Dann können Sie den Abzug vollständig entfernen. 

Ich empfehle, Tabellenaktualisierungsberechtigungen zu verweigern, wenn nichts anderes funktioniert.

Dies löst auch das Problem des doppelten Codes. Das Duplizieren von Code im Update SP und im Auslöser verstößt gegen die Grundsätze der Softwareentwicklung und wird zu einem Wartungsproblem.

6

ALTER TABLE tbl DISABLE TRIGGER trg

http://doc.ddart.net/mssql/sql70/aa-az_5.htm

Ich verstehe die Bedeutung Ihres ersten Absatzes jedoch nicht

4
devio

Ich bin mir nicht sicher, ob dies eine gute Idee ist, aber es scheint für mich zu funktionieren. Die Transaktion sollte Einfügungen von anderen Prozessen in die Tabelle verhindern, während der Trigger deaktiviert ist.

IF OBJECT_ID('dbo.TriggerTest') IS NOT NULL
 DROP PROCEDURE dbo.TriggerTest
GO

CREATE PROCEDURE [dbo].[TriggerTest]
AS
BEGIN TRANSACTION trnInsertTable1s
;
DISABLE TRIGGER trg_tblTable1_IU ON tblTable1
;
BEGIN -- Procedure Code
    PRINT '@@trancount'
    PRINT @@TRANCOUNT
    -- Do Stuff

END -- Procedure Code
;
ENABLE TRIGGER trg_tblTable1_IU ON tblTable1

IF @@ERROR <> 0 ROLLBACK TRANSACTION
ELSE COMMIT TRANSACTION
2
Steve

Da Sie angeben, dass der Auslöser Logik enthält, um alle Aktualisierungen zu handhaben, auch manuelle Aktualisierungen, sollte sich die Logik dort befinden. Das von Ihnen erwähnte Beispiel, dass eine gespeicherte Prozedur "für diese Logik sorgt", impliziert doppelten Code. Wenn Sie außerdem sicherstellen möchten, dass für jede UPDATE-Anweisung diese Logik unabhängig vom Autor angewendet wird, ist der Auslöser der Ort dafür. Was passiert, wenn jemand eine Prozedur erstellt, aber die Logik noch einmal kopiert? Was passiert, wenn es an der Zeit ist, die Logik zu ändern?

2
Pittsburgh DBA

Ich habe ein bisschen bei diesem einen Scherz gemacht. Auf der einen Seite bin ich sehr anti-triggerig, hauptsächlich weil es ein weiterer Platz ist, um nach Code zu suchen, der an meinem Tisch ausgeführt wird, zusätzlich zu den Gründen, die in dem Artikel angegeben sind, der in dem Frage-Post verlinkt ist. 

Wenn Sie jedoch über Logik verfügen, um stabile und unveränderliche Geschäftsregeln oder tabellenübergreifende Aktionen (z. B. das Verwalten einer Verlaufstabelle) durchzusetzen, ist es sicherer, dies in einen Trigger zu bringen, so dass sich Autoren und Programmierer von Prozeduren nicht befassen müssen damit - es funktioniert einfach. 

Meine Empfehlung ist also, die notwendige Logik in Ihren Auslöser einzufügen, anstatt in diesen einen Prozess, der zwangsläufig auf mehrere Prozesse mit derselben Ausnahme anwächst.

1
Rob Allen

Erwägen Sie, den Auslöser umzuschreiben, um die Leistung zu verbessern, wenn Leistung das Problem ist.

1
HLGEM

Deaktivieren Sie den Auslöser nicht. Sie haben Recht, das für gleichzeitige Transaktionen deaktiviert wird.

Warum möchten Sie den Abzug deaktivieren? Was tut es? Warum ist der Auslöser ein Problem? Es ist normalerweise keine gute Idee, einen Tigger aus Sicht der Datenintegrität zu deaktivieren. 

1
HLGEM

Ich bin gerade mit dem gleichen Problem konfrontiert und habe die folgende Lösung gefunden, die für mich funktioniert.

  1. Erstellen Sie eine permanente DB-Tabelle, die einen Datensatz für jeden Trigger enthält, den Sie deaktivieren möchten (z. B. refTriggerManager). Jede Zeile enthält den Auslösernamen (z. B. strTriggerName = 'myTrigger') und ein Bitflag (z. B. blnDisabled, Standardwert 0).

  2. Suchen Sie am Anfang des Auslöserkörpers im refTriggerManager nach strTriggerName = 'myTrigger'. Wenn blnDisabled = 1 ist, kehren Sie zurück, ohne den Rest des Triggercodes auszuführen. Andernfalls setzen Sie den Triggercode bis zum Abschluss fort. 

  3. Führen Sie in der gespeicherten Prozedur, in der Sie den Trigger deaktivieren möchten, Folgendes aus:


BEGINNEN SIE DIE TRANSAKTION

UPDATE refTriggerManager SET blnDisabled = 1 WHERE strTriggerName = 'myTrigger'

/ * UPDATE die Tabelle, die 'myTrigger' besitzt, die aber deaktiviert werden soll. Da refTriggerManager.blnDisabled = 1 ist, wird 'myTrigger' zurückgegeben, ohne seinen Code auszuführen. * /

UPDATE refTriggerManager SET blnDisabled = 0 WHERE triggerName = 'myTrigger'

/ * Optionaler abschließender UPDATE-Code, der den Auslöser auslöst. Da refTriggerManager.blnDisabled = 0 ist, wird 'myTrigger' vollständig ausgeführt. * /

COMMIT TRANSACTION


All dies findet innerhalb einer Transaktion statt, daher ist es von der Außenwelt isoliert und hat keine Auswirkungen auf andere UPDATEs in der Zieltabelle.

Hat jemand ein Problem mit diesem Ansatz?

Rechnung

0
Hoyacoder

Ich stimme anderen Antworten zu. Deaktivieren Sie den Auslöser nicht.

Dies ist eine reine Meinung, aber ich vermeide Auslöser wie die Pest. Ich habe sehr wenige Fälle gefunden, in denen ein Auslöser zur Durchsetzung von Datenbankregeln verwendet wurde. Es gibt offensichtliche Edge-Fälle in meiner Erfahrung, und ich habe nur meine Erfahrung, um diese Aussage zu treffen. Normalerweise habe ich Trigger gesehen, die zum Einfügen relationaler Daten verwendet wurden (dies sollte aus der Geschäftslogik erfolgen), zum Einfügen von Daten in die Berichtstabelle, dh zum Denormalisieren der Daten (dies kann mit einem Prozess außerhalb der Transaktion erfolgen) oder zum Transformieren der Daten irgendwie. 

Es gibt legitime Anwendungen für Auslöser, aber ich denke, dass es in der alltäglichen Geschäftsprogrammierung nur wenige sind. Dies hilft möglicherweise nicht bei Ihrem aktuellen Problem, aber Sie können den Auslöser ganz entfernen und die Arbeit des Auslösers auf andere Weise erledigen.

0
Jason Jackson

sie können die Funktion ' Exec ' verwenden, um die Trigger einer gespeicherten Prozedur zu deaktivieren und zu aktivieren. Beispiel: EXEC ('ENABLE TRIGGER dbo.TriggerName on dbo.TriggeredTable')

0
Nader Sghir