【问题标题】:Trigger to raise error, prevent delete, and audit attempt引发错误、防止删除和审计尝试的触发器
【发布时间】:2013-12-28 16:57:58
【问题描述】:

我正在尝试创建一个执行三件事的触发器: 1.防止删除特定表上的数据 2.为用户生成错误消息 3. 记录试图删除的数据以及 SQL 中的会话信息。

这是我目前的代码:

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

【问题讨论】:

标签: sql sql-server triggers audit


【解决方案1】:

在引发错误之前尝试提交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);

【讨论】:

  • 就是这样 - 我需要在引发错误之前提交数据。谢谢!
猜你喜欢
  • 2016-11-06
  • 2010-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-19
相关资源
最近更新 更多