检查SQL Server表的更改?

TimM 130 sql sql-server datatable rdbms

如何在不使用触发器或以任何方式修改数据库结构的情况下监视SQL Server数据库以查找表的更改?我首选的编程环境是.NET和C#.

我希望能够支持任何SQL Server 2000 SP4或更新版本.我的应用程序是另一家公司产品的螺栓式数据可视化.我们的客户群数以千计,因此我不想在每次安装时都要求我们修改第三方供应商的表.

通过"更改表",我的意思是更改表数据,而不是更改表结构.

最终,我希望更改在我的应用程序中触发事件,而不是必须间隔检查更改.


根据我的要求(没有触发器或模式修改,SQL Server 2000和2005),最好的行动方案似乎是BINARY_CHECKSUMT-SQL中使用该函数.我计划实施的方式是这样的:

每隔X秒运行以下查询:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

并将其与存储值进行比较.如果值已更改,请使用查询逐行遍历表:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

并将返回的校验和与存储的值进行比较.

Jon Galloway.. 94

看一下CHECKSUM命令:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

只要表格内容没有改变,每次运行时都会返回相同的数字.有关更多信息,请参阅我的帖子:

校验

以下是我在表更改时使用它来重建缓存依赖关系的方式:
ASP.NET 1.1数据库缓存依赖项(不带触发器)

  • 校验和最终会失败.如果您的系统接受两个不同的数据集将产生相同的校验和,那么您就没事了.出于这个原因,我不得不在大多数系统中摆脱校验和...... (2认同)

用户甲.. 30

不幸的是,CHECKSUM始终无法正常检测变化.它只是一个原始校验和,没有CRC计算.因此,您无法使用它来检测所有更改,例如,对称更改会导致相同的CHECKSUM!

E. g.CHECKSUM_AGG(BINARY_CHECKSUM(*))对于具有不同内容的所有3个表,该解决方案始终为0!


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 1 as numA, 2 as numB UNION ALL SELECT 1 as numA, 2 as numB ) q -- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 0 as numA, 0 as numB UNION ALL SELECT 0 as numA, 0 as numB ) q -- delivers 0!

  • 这实际上不是答案,而是"你的建议不起作用". (3认同)

Nick Berardi.. 26

你为什么不想使用触发器?如果你正确使用它们,它们是一件好事.如果您将它们用作强制参照完整性的一种方式,那就是它们从好的变为坏的时候.但是,如果你使用它们进行监控,它们并不真正被视为禁忌.


Chris Miller.. 20

您需要多久检查一次更改以及数据库中表的大小(以行大小计)?如果使用CHECKSUM_AGG(BINARY_CHECKSUM(*))John建议的方法,它将扫描指定表的每一行.该NOLOCK提示帮助,但对大型数据库,你还在打每一行.您还需要存储每行的校验和,以便告知其中一行已更改.

你有没有考虑从不同的角度去做这件事?如果您不想修改架构以添加触发器(从某种意义上说,它不是您的数据库),您是否考虑过与构建数据库的应用程序供应商合作?

他们可以实现一个API,该API提供一种机制,用于通知附件应用程序数据已更改.它可以像写入通知表一样简单,该通知表列出了哪些表和哪些行被修改.这可以通过触发器或应用程序代码实现.在您身边,ti无关紧要,您唯一关心的是定期扫描通知表.对数据库的性能影响远小于扫描每一行的变化.

困难的部分是说服应用程序供应商实现此功能.由于这可以通过SQL通过触发器完全处理,因此您可以通过编写和测试触发器然后将代码提供给应用程序供应商来完成大部分工作.通过让供应商支持触发器,它可以防止添加触发器无意中替换供应商提供的触发器的情况.


Yaakov Ellis.. 18

拥有以给定间隔运行的DTS作业(或由Windows服务启动的作业).每次运行时,它都会使用系统INFORMATION_SCHEMA表获取有关给定表的信息,并将此数据记录在数据存储库中.将返回的有关表结构的数据与上一次返回的数据进行比较.如果它不同,那么您就知道结构已经改变了.

返回有关表ABC中所有列的信息的示例查询(理想情况下只列出您想要的INFORMATION_SCHEMA表中的列,而不是像我这样使用*select**):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

您将监视不同的列和INFORMATION_SCHEMA视图,具体取决于您如何定义"对表的更改".


caryden.. 18

不幸的是,我认为在SQL2000中没有一种干净的方法可以做到这一点.如果您将要求缩小到SQL Server 2005(及更高版本),那么您就可以开展业务了.你可以使用该SQLDependency课程System.Data.SqlClient.请参阅SQL Server中的查询通知(ADO.NET).


Orion Edward.. 13

疯狂猜测:如果你不想修改第三方的表,你能创建一个视图,然后在该视图上设置一个触发器吗?


ECE.. 6

检查上次提交日期.每个数据库都有每个提交时间的历史记录.我相信它符合ACID标准.