为何将HASHBYTES生成的VARBINARY转CHAR再转回VARBINARY作为主键?
为什么要先转CHAR再转回VARBINARY生成MD5主键?
先看你贴出的原代码:
SELECT CONVERT(VARBINARY(32), CONVERT( CHAR(32), HASHBYTES('MD5', (LTRIM(RTRIM(COALESCE(column1,'')))+';'+LTRIM(RTRIM(COALESCE(column2,'')))) ), 2) ) FROM database.schema.table
首先明确:HASHBYTES('MD5', ...)直接返回的是16字节的VARBINARY(因为MD5是128位哈希,128/8=16字节),而这段代码转一圈后得到的是32字节的VARBINARY——本质是把MD5哈希的十六进制字符串(32个字符)再转回二进制。这么做的原因可能有以下几种:
- 适配旧字段定义:如果主键字段被定义为
VARBINARY(32),直接存16字节的哈希会因为长度不匹配报错或者截断。转成32字节的二进制就能刚好填满这个字段,兼容原有表结构。 - 调试与可读性:虽然最终存的是二进制,但中间转成CHAR的过程,方便开发/运维人员在查询数据时,不用额外转换就能看到哈希的十六进制明文(比如直接查字段值就能看到类似
098f6bcd4621d373cade4e832627b4f6的字符串)。如果直接存16字节二进制,查询结果是乱码,需要再转一次才能读,排查问题更麻烦。 - 避免隐式转换坑:有些场景下,16字节的VARBINARY和字符串类型交互时,可能触发意想不到的隐式转换(比如和VARCHAR拼接时自动转成乱码)。转成32字节的十六进制二进制,相当于把哈希的“可读形式”转成二进制存储,减少这类隐式转换带来的意外。
- 认知偏差导致的冗余:可能写代码的人误以为MD5哈希本身是32字节的,不知道
HASHBYTES直接返回的是压缩后的16字节结果,所以多做了一次无意义的转换。
当然这种做法也有缺点:存储空间翻倍(16→32字节),多了两次转换操作(虽然性能影响极小,但没必要的话完全可以省略)。如果你的主键字段是VARBINARY(16),直接用HASHBYTES('MD5', ...)更高效。
内容的提问来源于stack exchange,提问作者ulie
相关产品推荐
相关产品推荐

