似乎因为我正在做 hashbytes 的字段是 nvarchar(max),所以 hashbytes 的结果是 nvarchar(max)。
不,这是不可能的,尤其是因为HASHBYTES 的返回值是VARBINARY。此外,由于您的测试只是 SELECT 语句而不是 INSERT 语句,因此返回值无法获得截断错误。截断错误来自 input 值。正如 HASHBYTES 的链接 MSDN 页面中所述(对于 SQL Server 2012 和 2014):
允许的输入值限制为 8000 字节。输出符合算法标准:MD2、MD4、MD5为128位(16字节); SHA 和 SHA1 为 160 位(20 字节); SHA2_256 为 256 位(32 字节),SHA2_512 为 512 位(64 字节)。
这确实说明了一切:输入限制为 8000 字节,输出是基于指定算法的固定字节数。
针对 SQL Server 2016(已删除 8000 字节限制)的更新文档指出:
对于 SQL Server 2014 及更早版本,允许的输入值限制为 8000 个字节。
你可以运行一个简单的测试:
DECLARE @Test NVARCHAR(MAX) = REPLICATE(CONVERT(NVARCHAR(MAX), N't'), 50000);
SELECT LEN(@Test);
SELECT HASHBYTES('MD5', @Test);
返回:
50000
Msg 8152, Level 16, State 10, Line 3
String or binary data would be truncated.
如果要在 2016 之前的 SQL Server 版本中将超过 8000 个字节传递给哈希函数,则需要使用 SQLCLR。您可以编写自己的函数,也可以下载并安装SQL# SQLCLR 库(我创建的)的免费版本,并使用 Util_Hash 和 Util_HashBinary功能:
DECLARE @Test NVARCHAR(MAX) = REPLICATE(CONVERT(NVARCHAR(MAX), N't'), 50000);
SELECT LEN(@Test);
SELECT SQL#.Util_Hash('MD5', CONVERT(VARBINARY(MAX), @Test));
SELECT SQL#.Util_HashBinary('MD5', CONVERT(VARBINARY(MAX), @Test));
返回:
50000
40752EB301B41EEAEB309348CE9711D6
0x40752EB301B41EEAEB309348CE9711D6
更新
如果使用 VARCHAR(MAX) 列或变量但字符数不超过 8000(或 NVARCHAR(MAX) 列或变量不超过 4000 个字符),则不会出现问题,一切都会按预期工作:
DECLARE @Test VARCHAR(MAX) = REPLICATE('t', 5000);
SELECT LEN(@Test) AS [Characters],
HASHBYTES('MD5', @Test) AS [MD5];
返回:
5000 0x6ABFBA10B49157F2EF8C85862B6E6313