似乎因为我正在做 hashbytes 的字段是 nvarchar(max),所以 hashbytes 的结果是 nvarchar(max)。
不,这是不可能的,特别是因为HASHBYTES的返回值是 a VARBINARY
。此外,由于您的测试只是 SELECT 语句而不是 INSERT 语句,因此返回值无法获得截断错误。截断错误来自输入值。如链接的 MSDN 页面中所述HASHBYTES
(对于 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