欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

判断字段是否被更新 新旧数据写入Audit Log表中

程序员文章站 2023-12-04 12:23:52
insus.net解决这个问题,只有创建另外一个表,将存储用户决定要跟踪的表,以及这个表中需要跟踪的字段。 还要创建另外一个表[audit],就是存储跟踪记录的表: 复制代...
insus.net解决这个问题,只有创建另外一个表,将存储用户决定要跟踪的表,以及这个表中需要跟踪的字段。
还要创建另外一个表[audit],就是存储跟踪记录的表:
复制代码 代码如下:

audit
set ansi_nulls on
go
set quoted_identifier on
go
set ansi_padding on
go
create table [dbo].[audit](
[audit_nbr] [int] identity(1,1) not null,
[audittype] [char](1) not null,
[tablename] [nvarchar](128) not null,
[fieldname] [nvarchar](128) null,
[oldvalue] [nvarchar](4000) null,
[newvalue] [nvarchar](4000) null,
[username] [nvarchar](128) null,
[createdate] [datetime] not null,
primary key clustered
(
[audit_nbr] asc
)with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [primary]
) on [primary]
go
set ansi_padding off
go
alter table [dbo].[audit] with check add check (([audittype]='d' or [audittype]='u' or [audittype]='i'))
go
alter table [dbo].[audit] add default (getdate()) for [createdate]
go


解决是谁更新数据,是使用这个方法:在sql触发器或存储过程中获取在程序登录的用户
接下来,为跟踪表写一个更新trigger触发器。
在触发器中访问inserted或deleted的内部临时触发表,会得一个异常invalid object name 'inserted' 或是invalid object name 'deleted' ,解决此问题,可以参考这篇:
exec(execute)函数访问inserted或deleted的内部临时触发表
下面为表更新触发器(部分),有注释:
复制代码 代码如下:

--@n和@o两个变量,一个存储更新数据值,一个为原有数据值
declare @sql nvarchar(max),@n decimal(18,0),@o decimal(18,0)
--@i变量是用户需要跟踪的字段
set @sql = n'select @n = ['+ convert(nvarchar(max),@i) +'] from #inserted'
--执行动态sql语句。
execute sp_executesql @sql,
n'@n decimal(18,0) output',
@n output;
--下面sql代码,是从deleted表中获取原来数据值。
set @sql = n'select @o = ['+ convert(nvarchar(max),@i) +'] from #deleted'
execute sp_executesql @sql,
n'@o decimal(18,0) output',
@o output;
--对比两个数据值,更新值与原有值,如果不一样,把数据插入audit log表中。
if (isnull(@n,0) <> isnull(@o,0))
execute [dbo].[usp_audit_insert] 'u','<tablename>','<fieldname>',@o,@n,@username


上面代码还有一个存储过程,原因是如果多表或是一个表有更新或是删除需要把跟踪的数据插入audit log表中时,为了更好维护与代码冗余,因此把插入audit log表的过程,写成一个存储过程:
复制代码 代码如下:

usp_audit_insert
set ansi_nulls on
go
set quoted_identifier on
go
alter procedure [dbo].[usp_audit_insert]
(
@audittype [char](1),
@tablename [nvarchar](128),
@fieldname [nvarchar](128),
@oldvalue [nvarchar](4000),
@newvalue [nvarchar](4000),
@username [nvarchar](128)
)
as
insert into [dbo].[audit]
([audittype],[tablename],[fieldname],[oldvalue],[newvalue],[username])
values
(@audittype,@tablename,@fieldname,@oldvalue,@newvalue,@username)