【发布时间】: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