cni*_*nsd 5 sql sql-server audit triggers
我正在尝试创建一个触发器,它执行三项操作: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
Run Code Online (Sandbox Code Playgroud)
上面的代码能够阻止删除,并为用户引发错误.但是,没有任何内容输入审计表.如果我注释掉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
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)