在SQL服务器中,我们可以使用"校验和"轻松地在整行上生成哈希:
select
checksum(*), *
from mytable
有没有办法使用hashbytes函数做同样的事情? 类似的东西:
select
hashbytes('md5', *), *
from mytable
答案 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,C
与a,b,c
不同。同样,如果这是一个问题,你必须在散列之前调整数据(UPPER
)。
最后,MD5不再被认为是加密安全的,因此只能将此用于校验和索引等需要较少CHECKSUM
的碰撞概率。如果您需要一行的加密签名,这太简单了。