CHECKSUM_AGG似乎只是BINARY_CHECKSUM的结果相加为所有行。尽管每一行都改变了,但两个校验和的总和还没有(即17 + 32 = 16 + 33)。这是不是真的用于检查更新的规范,但我能想出的建议如下:
- 而不是使用
checksum_agg
的,串联校验为分隔字符串,字符串比较,沿行SELECT binary_checksum(*) + ',' FROM MyTable FOR XML PATH('')
。要检查和存储的字符串要长得多,但误判比较的可能性要小得多。
- 不使用内置校验和例程,而是使用HASHBYTES计算8000字节块中的MD5校验和,并将结果与xor结合在一起。这会给你一个更有弹性的校验和,虽然仍然不是防弹的(即它仍然有可能获得错误的匹配,但是不太可能)。我将粘贴下面我写的HASHBYTES演示代码。
- 最后一个选项和绝对最后的手段是以XML格式实际存储表格表并进行比较。这确实是您绝对可以确定没有错误匹配的唯一方式,但不可扩展并涉及存储和比较大量数据。
每种方法(包括您开始使用的方法)都有优点和缺点,不同程度的数据大小和处理要求与准确性有关。根据您需要的准确度级别,使用适当的选项。获得100%准确性的唯一方法是存储所有表格数据。
或者,您可以在每个表中添加一个date_modified字段,该表在插入和更新触发器后使用GetDate()设置。你可以做SELECT COUNT(*) FROM #test WHERE date_modified > @date_last_checked
。这是检查更新的更常见方式。这个缺点是不能跟踪删除。
另一种方法是创建一个带有table_name(VARCHAR)和is_modified(BIT)字段的修改表,其中包含您希望跟踪的每个表的一行。使用insert,update和delete触发器,针对相关表的标志被设置为True。当您运行计划时,将检查并重置is_modified标志(在同一事务中) - 沿着SELECT @is_modified = is_modified, is_modified = 0 FROM tblModified
的行 - 以下脚本生成三个结果集,每个结果集都与此响应中前面的编号列表相对应。我已经评论哪个输出与SELECT语句之前的哪个选项相对应。要查看输出是如何派生的,可以通过代码向后工作。
-- Create the test table and populate it
CREATE TABLE #Test (
f1 INT,
f2 INT
)
INSERT INTO #Test VALUES(1, 1)
INSERT INTO #Test VALUES(2, 0)
INSERT INTO #Test VALUES(2, 1)
/*******************
OPTION 1
*******************/
SELECT CAST(binary_checksum(*) AS VARCHAR) + ',' FROM #test FOR XML PATH('')
-- Declaration: Input and output MD5 checksums (@in and @out), input string (@input), and counter (@i)
DECLARE @in VARBINARY(16), @out VARBINARY(16), @input VARCHAR(MAX), @i INT
-- Initialize @input string as the XML dump of the table
-- Use this as your comparison string if you choose to not use the MD5 checksum
SET @input = (SELECT * FROM #Test FOR XML RAW)
/*******************
OPTION 3
*******************/
SELECT @input
-- Initialise counter and output MD5.
SET @i = 1
SET @out = 0x00000000000000000000000000000000
WHILE @i <= LEN(@input)
BEGIN
-- calculate MD5 for this batch
SET @in = HASHBYTES('MD5', SUBSTRING(@input, @i, CASE WHEN LEN(@input) - @i > 8000 THEN 8000 ELSE LEN(@input) - @i END))
-- xor the results with the output
SET @out = CAST(CAST(SUBSTRING(@in, 1, 4) AS INT)^CAST(SUBSTRING(@out, 1, 4) AS INT) AS VARBINARY(4)) +
CAST(CAST(SUBSTRING(@in, 5, 4) AS INT)^CAST(SUBSTRING(@out, 5, 4) AS INT) AS VARBINARY(4)) +
CAST(CAST(SUBSTRING(@in, 9, 4) AS INT)^CAST(SUBSTRING(@out, 9, 4) AS INT) AS VARBINARY(4)) +
CAST(CAST(SUBSTRING(@in, 13, 4) AS INT)^CAST(SUBSTRING(@out, 13, 4) AS INT) AS VARBINARY(4))
SET @i = @i + 8000
END
/*******************
OPTION 2
*******************/
SELECT @out
相关问题:http://stackoverflow.com/questions/7362312/is-there-a-function-feature-in-sql-server-to-determine-if-a-table-has-any -recen –
尝试在您的基表中添加'timestamp' /'rowversion'列。 – wqw