我的一个新客户有一个2002年编写的小型VB / Access数据库应用程序,他希望重写它以使其更新,并支持他一直想要的新功能。因此,我将在本地计算机上将其转换为使用C#.NET 2008和SQL Server Express 2008,并能够扩展到在远程服务器上使用WCF和SQL Server 2008。
他感兴趣的新功能之一是维护和报告一段时间内数据更改的完整历史记录。在过去,我通过使用触发器和存储过程完成了这项工作,这对@!#$来说很痛苦。
我最近惹恼了SQL Server 2008的更改数据捕获功能。在我玩它的最初时刻,我意识到它在SQL Agent中创建了一个默认每5秒运行一次的作业。当我需要更改捕获的表的模式时,它似乎也有点痛苦。除此之外,它似乎比我原来的方法更容易实现。所以,这些是我的问题:
谢谢,
马克
答案 0 :(得分:2)
CDC仅适用于SQL Server企业版。因此,如果你表达了你不能使用它,你将不得不留下触发器。
答案 1 :(得分:1)
虽然触发器在很多方面都很难用,但是您可以在透明的数据审计历史记录机制上使用它们,而不会对主代码库产生任何影响,方法是编写实际生成触发器的脚本和历史表自动。这是一项相当多的工作,我不知道有谁做过这样的事情并且开源了它,但它可能是一个有趣的项目。至少在这种情况下,您可以编写一个生成器过程,然后再也不必弄乱各个触发器。
答案 2 :(得分:1)
我在变更表中使用了我自己的变更数据跟踪系统,使其更加灵活。也使触发器相当通用。
假设您已经有触发器来创建审计行,并且您的源表中有一个名为“Version”的列,其类型为ROWVERSION:
INSERT INTO [Changes].Sites
(
SiteID,
Operation,
Version,
ModifiedOn,
DataChange
)
SELECT
IsNull( I.SiteID, D.SiteID ),
CASE
WHEN D.[Version] IS NULL AND I.[Version] IS NOT NULL THEN 'I'
WHEN D.[Version] IS NOT NULL AND I.[Version] IS NOT NULL THEN 'U'
WHEN D.[Version] IS NOT NULL AND I.[Version] IS NULL THEN 'D'
ELSE '?'
END,
IsNull( I.Version, D.Version ),
SysDateTimeOffset(),
(
SELECT
[Deleted] = ( SELECT * FROM deleted D1 WHERE D1.SiteID = D.SiteID FOR XML PATH(''), TYPE ),
[Inserted] = ( SELECT * FROM inserted I1 WHERE I1.SiteID = I.SiteID FOR XML PATH(''), TYPE )
FOR XML PATH('Changes')
)
FROM deleted D
FULL JOIN inserted I
ON D.SiteID = I.SiteID
该查询中唯一特定于我的表的是主键。生成模板以创建这些查询将非常简单(甚至可以使用sys.tables等在SQL中执行此操作)。