有时候我们数据库表中的数据会莫名其妙的被删除,不知道是业务问题还是被黑了,所以我们想要在数据库操作层面对此进行制止,同时记录操作的日志,我们可以利用触发器来实现这个需求,测试数据:
--测试数据 if not object_id(N'T') is null drop table T Go Create table T([ID] int,[姓名] nvarchar(22)) Insert T select 1,N'张三' union all select 2,N'李四' union all select 3,N'王五' GO --测试数据结束
新建日志表:
CREATE TABLE TBLOG ( ID INT NOT NULL IDENTITY(1, 1) , EVTIME DATETIME NOT NULL DEFAULT ( GETDATE() ) , --访问时间 [SQL] VARCHAR(300) , --执行的SQL语句 USERID VARCHAR(128) NOT NULL DEFAULT ( SUSER_SNAME() ) , --连接的时候使用的哪个SQL登陆用户 HOSTNAME VARCHAR(128) NOT NULL DEFAULT ( HOST_NAME() ) , --客户端的机器名 LOGINID VARCHAR(128), --客户端的登陆用户(OS的用户) APPNAME VARCHAR(128)NOT NULL DEFAULT ( APP_NAME()) --是从查询分析器,还是应用程序来执行的 )
新建触发器:
CREATE TRIGGER TR_TBTEST ON T FOR DELETE AS RAISERROR('错误',16,8) ROLLBACK TRAN --SQL CREATE TABLE #T ( EVENTTYPE VARCHAR(20) , PARAMETERS INT , EVENTINFO VARCHAR(300) ) DECLARE @SPID VARCHAR(20) SET @SPID = CAST(@@SPID AS VARCHAR) INSERT #T EXEC ( 'DBCC INPUTBUFFER (' + @SPID + ')' ) --进程信息 DECLARE @USERID VARCHAR(128) , --连接的时候使用的哪个SQL登陆用户 @HOSTNAME VARCHAR(128) , --客户端的机器名 @LOGINID VARCHAR(128) , --客户端的登陆用户(OS的用户) @APPNAME VARCHAR(128) --是从查询分析器,还是应用程序来执行的 SELECT @USERID = LOGINAME , --连接的时候使用的哪个SQL登陆用户 @HOSTNAME = HOSTNAME , --客户端的机器名 @LOGINID = NT_USERNAME , --客户端的登陆用户(OS的用户) @APPNAME = PROGRAM_NAME --是从查询分析器,还是应用程序来执行的 FROM MASTER..SYSPROCESSES WHERE SPID = @@SPID INSERT TBLOG ( SQL , USERID , HOSTNAME , LOGINID , APPNAME ) SELECT EVENTINFO , @USERID , @HOSTNAME , @LOGINID , @APPNAME FROM #T GO
测试删除:
DELETE FROM T WHERE id=1
结果:
查询日志和数据情况:
SELECT * FROM TBLOG SELECT * FROM T
结果:
以上实现了我们想要的禁止删除并添加日志的功能,当然我们也可以把这个应用到INSERT、UPDATE等操作中。