2013-12-10 4 views
5

Ich versuche, einen Auslöser zu schaffen, die drei Dinge tut: 1. Verhindert das Löschen von Daten auf einer bestimmten Tabelle 2. Erzeugt eine Fehlermeldung für den Benutzer 3. Protokolliert die Daten, die gelöscht werden sollen, zusammen mit Sitzungsinformationen aus SQL.Trigger-Fehler zu erhöhen, verhindern löschen, und Audit Versuch

Dies ist der Code, den ich bisher habe:

CREATE TRIGGER [dbo].[MyTable_prevent_delete_and_audit] 
ON [dbo].[MyTable] 
INSTEAD OF DELETE AS 
     BEGIN 
      DECLARE @SESSIONINFO nvarchar(200) 
      SELECT @SESSIONINFO = (RTRIM(LTRIM(CAST(login_time as nvarchar(20)))) + ' ' 
      + RTRIM(LTRIM(hostname)) + ' ' + RTRIM(LTRIM(program_name)) + ' ' 
      + RTRIM(LTRIM(cmd)) + ' ' + RTRIM(LTRIM(loginame))) from sys.sysprocesses WHERE spid = @@SPID 
      INSERT INTO [dbo].[MyTable_AUDIT] ([Field1],[Field1],[SESSIONINFO]) 
      SELECT [Field1],[Field1],@SESSIONINFO FROM deleted 
      RAISERROR ('Removing MyTable entries prevented by trigger. Contact your administrator', 16, 1) 
     END 
     RETURN 
GO 

Der obige Code der Lage ist, das Löschen zu verhindern, und den Fehler für den Benutzer zu erhöhen. In die Audit-Tabelle wird jedoch nie etwas eingetragen. Wenn ich die RAISEERROR-Zeile auskommentiere, fügt der Trigger korrekt Elemente zur Audit-Tabelle hinzu, aber natürlich werden die Daten gelöscht. Ich denke, ich muss etwas Einfaches vermissen (ist gelöscht nicht verfügbar, wenn ich einen Fehler erstelle?), Oder ein Element des Konzepts missverstehen. Bitte zeig mir den Fehler meiner Wege! :)

Bearbeiten: Aaron Bertrand hat die richtige Antwort, ich muss meine Audit-Daten vor der Erhöhung des Fehlers begehen. Die RAISERROR rollt im Wesentlichen alles zurück, einschließlich der Prüfung:

CREATE TRIGGER [dbo].[MyTable_prevent_delete_and_audit] 
ON [dbo].[MyTable] 
INSTEAD OF DELETE AS 
     BEGIN 
      DECLARE @SESSIONINFO nvarchar(200) 
      SELECT @SESSIONINFO = (RTRIM(LTRIM(CAST(login_time as nvarchar(20)))) + ' ' 
      + RTRIM(LTRIM(hostname)) + ' ' + RTRIM(LTRIM(program_name)) + ' ' 
      + RTRIM(LTRIM(cmd)) + ' ' + RTRIM(LTRIM(loginame))) from sys.sysprocesses WHERE spid = @@SPID 
      INSERT INTO [dbo].[MyTable_AUDIT] ([Field1],[Field1],[SESSIONINFO]) 
      SELECT [Field1],[Field1],@SESSIONINFO FROM deleted 
      COMMIT TRANSACTION; 
      RAISERROR ('Removing MyTable entries prevented by trigger. Contact your administrator', 16, 1) 
     END 
     RETURN 
GO 
+0

http://stackoverflow.com/questions/3266401/delete-records-within-instead-of-delete-trigger – granadaCoder

Antwort

4

Versuchen Sie, die INSERT vor dem Anheben der Fehler zu begehen. Andernfalls wird durch das Anheben des Fehlers alles zurückgesetzt, was der Trigger getan hat, und alles, was die Anweisung, die den Trigger aufgerufen hat, getan hat.

INSERT INTO [dbo].[MyTable_AUDIT] ([Field1],[Field1],[SESSIONINFO]) 
    SELECT [Field1],[Field1],@SESSIONINFO FROM deleted; 

COMMIT TRANSACTION; 

RAISERROR ('Removing MyTable entries prevented by trigger. ...', 16, 1); 
+0

Das war es - ich die Daten verpflichten musste, bevor die Fehler zu erhöhen. Vielen Dank! – cninsd

Verwandte Themen