我有一个sql server 2012数据库。我有一个changeLog
表包含
TableName, ColumnName, FromValue
和ToValue
列。这将用于跟踪修改的列和数据。
因此,如果通过应用程序进行任何更新,则只有修改过的列应该使用其新旧值插入此表中。
任何人都可以帮助我。
例如:
如果过程更新属性表的所有列(propertyName, address
)
然后,如果用户更新propertyName
(但更新还包含address
列,但没有数据更改),则只有propertyName
及其数据将插入ChangeLog
表而不是{{1由于address
数据不包含任何数据更改,因此列及其数据。
答案 0 :(得分:1)
IF 根本没有其他审计要求 - 没有这个,你不会以任何方式考虑审计 - 那么好吧,去吧。然而,这是一个非常有限的审计使用:用户X在时间Y改变了这个字段。一般来说,这是一个更广泛的问题的一部分:用户X做了什么?数据库中的客户数据发生了什么,最终以现在的方式结束了?
如果您拥有自己建议的数据结构并且重建繁重,那么这样的问题就更难回答。我通常的做法如下。从像这样的基表开始(这来自我当前的一个项目):
CREATE TABLE [de].[Generation](
[Id] [int] IDENTITY(1,1) NOT NULL,
[LocalTime] [datetime] NOT NULL,
[EntityId] [int] NOT NULL,
[Generation] [decimal](18, 4) NOT NULL,
[UpdatedAt] [datetime] NOT NULL CONSTRAINT [DF_Generation_UpdatedAt] DEFAULT (getdate()),
CONSTRAINT [PK_Generation] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
(我已经排除了FK定义,因为它们在这里并不相关。)
首先为此表创建一个Audit表:
CREATE TABLE [de].[GenerationAudit](
[AuditId] int identity(1, 1) not null,
[Id] [int] NOT NULL,
[LocalTimeOld] [datetime] NULL,
[EntityIdOld] [int] NULL,
[GenerationOld] [decimal](18, 4) null,
[UpdatedAtOld] [datetime] null,
[LocalTimeNew] [datetime] null,
[EntityIdNew] [int] null,
[GenerationNew] [decimal](18, 4) null,
[UpdatedAtNew] [datetime] NOT NULL CONSTRAINT [DF_GenerationAudit_UpdatedAt] DEFAULT (getdate()),
[UpdatedBy] varchar(60) not null
CONSTRAINT [PK_GenerationAudit] PRIMARY KEY CLUSTERED
(
[AuditId] ASC
)
此表格中每列的*旧版本和*版本都无法更改。作为IDENTITY PK的ID不能改变,所以不需要旧的/新的。我还添加了一个UpdatedBy列。它还有一个新的AuditId IDENTITY PK。
接下来在基表上创建三个触发器:一个用于INSERT,一个用于UPDATE,一个用于DELETE。在Insert触发器中,在Audit表中插入一行,其中从inserted表中选择New列,Old值为null。在UPDATE中,Oldvalues来自已删除而新来自插入。在DELETE触发器中,old from from deleted和new都是null。
UPDATE触发器如下所示:
CREATE TRIGGER GenerationAuditUpdate
ON de.Generation
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
insert into de.GenerationAudit (Id, LocalTimeOld, EntityIdOld, GenerationOld, UpdatedAtOld,
LocalTimeNew, EntityIdNew, GenerationNew, UpdatedAtNew,
UpdatedBy)
select isnull(i.Id, d.Id), d.LocalTime, d.EntityId, d.Generation, d.UpdatedAt,
i.LocalTime, i.EntityId, d.Generation, getdate(),
SYSTEM_USER)
from inserted i
full outer join deleted d on d.Id = i.Id;
END
GO
然后,您可以获得每个更改的完整前/后图片(并且它将比逐列分离差异更快)。您可以在Audit表上创建视图,以获取Old值与new不同的条目,并包括基表Id(您的结构中也需要它!),执行它的用户以及它们执行的时间它(UpdatedAtNew)。
那是我的审计版本,它是我的!