目前,每个表的触发器对于表中的每个字段都是这样的:
ALTER TRIGGER [dbo].[trg_Statement] ON [dbo].[tbl_Statement]
FOR INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO tbl_ChangeLog(TableName, ID, FieldName, OldValue, NewValue)
SELECT
'Statement', CU.id, 'id', deleted.id,inserted.id
FROM
tbl_Statement CU
LEFT JOIN
inserted on CU.id = inserted.id
LEFT JOIN
deleted on CU.id = deleted.id
WHERE
(inserted.id is not null or deleted.id is not null)
AND IsNull(inserted.id,'') <> IsNull(deleted.id,'')
INSERT INTO tbl_ChangeLog(TableName, ID, FieldName, OldValue, NewValue)
SELECT
'Statement', CU.id, 'idAccount', deleted.idAccount,inserted.idAccount
FROM
tbl_Statement CU
LEFT JOIN
inserted on CU.id = inserted.id
LEFT JOIN
deleted on CU.id = deleted.id
WHERE
(inserted.id is not null or deleted.id is not null)
AND IsNull(inserted.idAccount,'') <> IsNull(deleted.idAccount,'')
INSERT INTO tbl_ChangeLog(TableName, ID, FieldName, OldValue, NewValue)
SELECT
'Statement', CU.id, 'OpeningBalance', deleted.OpeningBalance,inserted.OpeningBalance
FROM
tbl_Statement CU
LEFT JOIN
inserted on CU.id = inserted.id
LEFT JOIN
deleted on CU.id = deleted.id
WHERE
(inserted.id is not null or deleted.id is not null)
AND IsNull(inserted.OpeningBalance,'') <> IsNull(deleted.OpeningBalance,'')
...
然而,这是非常昂贵的,特别是当有很多字段时,是否有人可以提出更有效的方法来跟踪我们的更改日志的更改?
答案 0 :(得分:2)
我同意麦迪逊,你的AUDIT表中的一行包含整个记录将更有用,性能更高。基表越宽,这就越真实。在你的情况下:
CREATE TRIGGER IUD_Statement_Audit
ON dbo.tbl_Statement AFTER INSERT, UPDATE, DELETE
AS BEGIN
IF (@@rowCount = 0) RETURN;
SET NOCOUNT ON;
INSERT INTO dbo.tbl_Statement_AUDIT
(id, idAccount, OpeningBalance, insertedOrDeleted, modTime, modId)
SELECT id, idAccount, OpeningBalance, 'D', GETDATE(), USER_NAME() FROM DELETED
UNION ALL
SELECT id, idAccount, OpeningBalance, 'I', GETDATE(), USER_NAME() FROM Inserted
END
此方法有许多好处,包括:在id列上轻松连接,以查看所有表的所有更改和触发器成为复制/粘贴练习。通常,RDBMS对于宽表(包含所有列的一个记录)和较少的记录(而不是一个skinny [?]表)(每个列更改一个记录)将表现更好。您当前的方法将为每个插入,删除和更新的记录创建三条记录。
回滚到过去的点可以通过按modTime desc, insertedOrDeleted desc
对审计表进行排序并执行反向操作...然后返回到您想要的位置。
答案 1 :(得分:1)
我有时会为要记录的表创建一个相同的表,除了我添加一个新的身份主键和一个datetime字段来跟踪更改发生的时间。然后,只要原始表发生更改,我就会在跟踪表中插入已更改的整行以及当前日期时间。
这方面的优点是它易于实现,并允许在需要时回滚到前一组值。如果您想查看总历史记录,它还允许轻松连接到当前行(如果您经常这样做,请记得索引)。此外,在您的情况下,它只是一个插入,除了抓取正确的行之外没有逻辑。缺点是它会在每次更改时存储所有字段,并且您必须维护两个表。
您显然可以减少您不希望以其他方式跟踪或修改此字段的字段,以满足您的需求。例如,如果行被删除,您可能希望在跟踪表中保留一个额外的字段。
为了查看旧值和新值,您需要在日期中向后查看日期,以查看更改时间。
答案 2 :(得分:0)
我认为Log Trigger中描述的方法更短,更快,更清晰。它不存储&#34;类型&#34;更改,例如插入,更新或删除,而是创建一个名为Tuple versioning的结构。插入是没有先前&#34;版本&#34;的行,删除是没有subsecuent的行&#34;版本&#34;,中间行是更新。
它的优势在于,在特定时间点检索特定实体的数据更容易,也更自然。
事实上,很容易了解整个桌子在特定时间点的情况。如果表格变得混乱并且需要从给定的“安全”表中恢复数据,这将非常有用。时间点。