2009-09-25 60 views
3

关于如何审计表的话题最近出现在我们的讨论中...所以我喜欢你的意见,最好的办法是什么来解决这个问题。在我们的数据库中,我们有两种方法的组合(这不是很好),因为之前的每个DBA都做了他/她认为正确的方法。所以我们需要改变他们遵循任何一个模型。审计触发器:使用INSERTED或DELETED系统表

CREATE TABLE dbo.Sample(
Name VARCHAR(20), 
... 
... 
Created_By VARCHAR(20), 
Created_On DATETIME, 
Modified_By VARCHAR(20), 
Modified_On DATETIME 
) 

CREATE TABLE dbo.Audit_Sample(
Name VARCHAR(20), 
... 
... 
Created_By VARCHAR(20), 
Created_On DATETIME, 
Modified_By VARCHAR(20), 
Modified_On DATETIME 
Audit_Type VARCHAR(1) NOT NULL 
Audited_Created_On DATETIME 
Audit_Created_By VARCHAR(50) 
) 

方法1:商店,在审计表从主表中删除对于被替换,只有那些记录/(使用系统表删除)。因此,对于主表中的每个UPDATE和DELETE,正在被替换的记录被插入审计表中,其中'Audit_Type'列为萎凋'U'(用于UPDATE)或'D'(用于DELETE)

INSERT未经审核。对于任何记录的当前版本,您总是查询主表。对于历史记录,您可以查询审计表。

优点:似乎很直观,用于存储以前版本的记录 缺点:如果您需要了解特定记录的历史记录,则需要将审计表与主表连接起来。

Appraoch 2:在审计表中存储每个进入主表的记录(使用系统表INSERTED)。

INSERTED/UPDATED/DELETED到主表的每条记录也存储在审计表中。所以当你插入一条新记录时,它也被插入到审计表中。更新后,新版本(来自INSERTED)表存储在审计表中。被删除时,旧版本(来自DELETED)表被存储在审计表中。优点:如果您需要了解特定记录的历史记录,则可以在一个位置查看所有记录。

虽然我没有在这里列出所有这些,每种方法都有其优点和缺点吗?

回答

4

我会去用:

Appraoch 2:存储,在审计表中,每一个进入主表 (利用插入系统表)记录。

是每行一行真的会杀死数据库吗?这样你就可以完整地记录下历史。

如果您清除出列(一个范围内的所有比X天以上),你仍然可以告诉我们,如果事情已经改变与否:

  • 如果审计行存在(尚未清除),你可以看到,如果行问题改变了。
  • 如果该项目不存在审计行(全部被清除)什么都没有改变(因为任何改变写入审计表,其中包括全新的项目)

如果用Appraoch 1走:和清除了范围内,它将很难(需要记住清除日期)告诉新的插入与清除所有行的插入。

+0

在我把所有的想法写进这个问题后,重新阅读之后,我也有同样的想法。方法2似乎是一个更好的方法。小小的头顶可以忽略不计。感谢您的输入。 – 2009-09-25 18:20:26

0

我们使用很多第三种方法是只审核感兴趣的列,并在每一行保存'新'和'旧'值。

因此,如果您有“名称”列,审计表将具有“name_old”和“name_new”。

在INSERT触发器中,根据您的偏好将“name_old”设置为空/ null,并且“name_new”设置为INSERTED。 在UPDATE触发器中,“name_old”设置为DELETED,而来自INSERTED的“name_new”设置为 在DELETE触发器中,将“name_old”设置为DELETED,将“new_name”设置为blank/null。

(或您使用FULL加入和所有情形之一的触发)

对于VARCHAR领域,这可能看起来不像一个好主意,但对于INTEGER,DATETIME等提供,它是非常受益容易看到更新的区别。

I.e.如果你在你的真正的表有一个量场,并从5更新到7,你必须在审计表:

quantity_old quantity_new 
      5    7 

轻松就可以计算出的数量是在特定的时间增加了2个。

如果您在审计表中有单独的行,您将不得不加入一行以“下一个”计算差异 - 在某些情况下这可能会非常棘手......

+0

感谢您的回复。我以前听说过这种方法,但从未实现过。我会进一步思考。 谢谢, _UB – 2009-09-25 17:34:48