我怎样才能使用校验和等哈希字节?

时间:2015-02-18 10:58:03

标签: sql-server hash checksum

在SQL服务器中,我们可以使用"校验和"轻松地在整行上生成哈希:

select 
checksum(*), *    
from mytable

有没有办法使用hashbytes函数做同样的事情? 类似的东西:

select 
hashbytes('md5', *), *    
from mytable

2 个答案:

答案 0 :(得分:2)

我不害怕。在大多数情况下,你不应该真的想要。但是,如果必须,为每行生成XML文档并散列XML文档可能是最简单的方法:

SELECT  HASHBYTES('MD5', X.value)
FROM    Data
CROSS APPLY (
    SELECT value = 
        CAST((SELECT Data.* FROM   (SELECT 1) AS X (y) FOR XML AUTO) AS VARCHAR(MAX))
) AS X

编辑:我已经进行了一些测试,应用CAST(... AS VARCHAR(MAX)),因为我在上面的更新声明中所做的工作提高了15%左右的性能。更重要的是,它可以防止宽表上的截断错误。即使在此修复程序仍然快15%之后,自己连接列也是如此。使用CONCAT()(可从MSSQL 2012获得)函数可以让您的实时更轻松,因为您可以省略将ISNULL和CAST函数应用于每一列。

答案 1 :(得分:1)

如果写出列没有异议,你可以简单地连接列和哈希:

SELECT HASHBYTES('md5', 
    ISNULL(CONVERT(VARBINARY(MAX), column1), 0x) +
    ISNULL(CONVERT(VARBINARY(MAX), column2), 0x) + 
    ...
)

从SQL Server 2012开始,我们可以使用CONCAT更紧凑地实现相同的目标(感谢@MWillemse提供的建议):

SELECT HASHBYTES('md5', CONCAT(column1, column2, ...))

请注意,如果您的列“相同”,这可能会导致冲突:哈希AA,BB,CC会产生与AAB,BBC,C甚至AABBCC,NULL,NULL相同的结果。如果这是一个问题,您将必须设计自己的散列方案,以最大限度地减少这种情况(例如,通过在散列中包含列名称)。此外,这是二进制校验和:哈希A,B,Ca,b,c不同。同样,如果这是一个问题,你必须在散列之前调整数据(UPPER)。

最后,MD5不再被认为是加密安全的,因此只能将此用于校验和索引等需要较少CHECKSUM的碰撞概率。如果您需要一行的加密签名,这太简单了。