为什么CHECKSUM_AGG()为完全不同的输入值返回相同的值?

时间:2014-10-06 17:07:41

标签: tsql

我真的不知道CHECKSUM_AGG()是如何工作的,虽然我知道它是通过使用XOR以某种方式构建的。这解释了为什么当你传递相等的整数时它会返回0

但为什么我在以下SQL中得到相同的聚合校验和,其中输入值是唯一的?

DECLARE @test1 TABLE (chksum INT)
INSERT INTO @test1 VALUES (2147473855), (2147473343)
SELECT CHECKSUM_AGG(chksum)
FROM @test1

DECLARE @test2 TABLE (chksum INT)
INSERT INTO @test2 VALUES (2147474831), (2147472271)
SELECT CHECKSUM_AGG(chksum)
FROM @test2

非常感谢您的解释。谢谢!

1 个答案:

答案 0 :(得分:3)

SQL Server CHECKSUM和CHECKSUM_AGG实现存在已知问题:CHECKSUM weakness explained

改为使用HASHBYT:Using HASHBYTES to compare columns

来自Microsoft: 如果表达式列表中的某个值发生更改,则列表的校验和通常也会更改。但是,校验和不会发生变化的可能性很小。因此,我们不建议使用CHECKSUM来检测值是否已更改,除非您的应用程序可以容忍偶尔错过更改。 考虑使用HashBytes 。当指定MD5哈希算法时,HashBytes为两个不同输入返回相同结果的概率远低于CHECKSUM。

您不能直接跨行使用HASHBYTES - 有一种解决方法here

以下是较小数字的比较,使用HASBYTES解决方法:

DECLARE @test1 TABLE (chksum INT) 
DECLARE @test2 TABLE (chksum INT)

INSERT INTO @test1 VALUES (50), (3), (26)
INSERT INTO @test2 VALUES (45), (0), (6)

SELECT [Values]    = '50, 3, 26', 
       [Checksum]  = CHECKSUM_AGG(chksum),
       -- HashBytes is limited to 8000 bytes only
       [Hashbytes] = HashBytes('md5',convert(varbinary(max),(SELECT * FROM @test1 FOR XML AUTO)))
FROM @test1

UNION ALL
SELECT  [Values]    = '45, 0, 6',      
        [Checksum]  = CHECKSUM_AGG(chksum),
        -- HashBytes is limited to 8000 bytes only
        [Hashbytes] = HashBytes('md5',convert(varbinary(max),(SELECT * FROM @test2 FOR XML AUTO)))
FROM @test2

CHECKSUM_AGG vs HASHBYTES