2013-12-10 7 views
5

する:1.特定のテーブルにデータの削除を禁止し 2. は、ユーザー のためのエラーメッセージを生成します3.削除しようとしたデータをSQLのセッション情報とともに記録します。トリガーは、私は3つのことを行い、トリガーを作成しようとしてる、エラーが発生し、削除防止し、及び監査の試み

これは私がこれまで持っているコードです:上記のコードは削除を防止し、ユーザーのためにエラーを発生させることが可能である

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 

。ただし、監査テーブルには何も入力されません。 RAISEERROR行をコメントアウトすると、トリガーは監査テーブルに項目を正しく追加しますが、もちろんデータは削除されます。私は、単純なものが欠けていなければならないと思っています(私はエラーを起こしているなら削除できませんか?)、または概念のいくつかの要素を誤解しています。私の方法の誤りを私に見せてください! :)

編集:Aaron Bertrandが正しい答えを示しています。エラーを発生させる前に監査データをコミットする必要があります。 RAISERRORは、本質的に監査を含むバックのすべてを、ロール:

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

答えて

4

エラーを上げる前INSERTをコミットしてみてください。それ以外の場合は、エラーを発生させると、トリガーが行ったすべての処理と、トリガーを呼び出したステートメントがロールバックされます。

それだった
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

- 私は、エラーを上げる前にデータをコミットする必要がありました。ありがとうございました! – cninsd

関連する問題