2013-12-10 7 views
5

sto cercando di creare un trigger che fa tre cose: 1. Impedisce la cancellazione dei dati su una particolare tabella 2. genera un messaggio di errore per l'utente 3. Registra i dati che è stato tentato di eliminare insieme alle informazioni di sessione di SQL.trigger per aumentare l'errore, a prevenire eliminare e revisione contabile tentativo

Questo è il codice che ho finora:

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 

Il codice di cui sopra è in grado di prevenire la cancellazione, e sollevare l'errore per l'utente. Tuttavia, nulla è mai entrato nella tabella di controllo. Se commento la riga RAISEERROR, il trigger aggiunge correttamente elementi alla tabella di controllo, ma ovviamente i dati vengono cancellati. Sto pensando che mi debba mancare qualcosa di semplice (è stato cancellato non disponibile se ho generato un errore?), O frainteso qualche elemento del concetto. Per favore mostrami l'errore dei miei modi! :)

Modifica: Aaron Bertrand ha la risposta corretta, devo impegnare i miei dati di controllo prima di generare l'errore. Il RAISERROR rotola in sostanza tutto torna, compreso l'audit:

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

risposta

4

Prova commettere il INSERT prima di sollevare l'errore. Altrimenti, sollevando l'errore, viene eseguito il rollback di tutto ciò che ha fatto il trigger e tutto ha fatto la dichiarazione che ha invocato il trigger.

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

Questo è tutto - avevo bisogno di impegnare i dati prima di sollevare l'errore. Grazie! – cninsd

Problemi correlati