Joh*_*ohn 9 sql-server hashbytes
使用SQL Server 2014我有,有一个表nvarchar(max)称为列[ASCII File]其中可以包含很多K的ASCII文本文件,然后我想这样做对文件和结果哈希应该永远是20个字节的MD5 HASHBYTES.
好吧,当我做一个选择hashbytes('MD5', [ASCII File])我得到查询完成错误
消息8152,级别16,状态10,行4
字符串或二进制数据将被截断.
我尝试时收到同样的信息
left(hashbytes('MD5', [ASCII File]), 50)
Run Code Online (Sandbox Code Playgroud)
我尝试时收到同样的信息
convert(varchar(50), hashbytes('MD5', [ASCII File]))
Run Code Online (Sandbox Code Playgroud)
似乎自从我正在进行哈希字节的列时,哈希nvarchar(max)字节函数的结果也是如此nvarchar(max).
你能告诉我如何才能让结果成为预期的20长,而不是这么长时间它必须被截断吗?
Sol*_*zky 10
看起来,因为我正在进行哈希字节的字段是nvarchar(max),所以hashbytes的结果是nvarchar(max).
不,这是不可能的,特别是因为HASHBYTES的返回值是a VARBINARY.此外,由于您的测试只是SELECT语句而不是INSERT语句,因此返回值无法获得截断错误.截断错误来自输入值.如HASHBYTES(针对SQL Server 2012和2014)的链接MSDN页面所述:
允许的输入值限制为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);
Run Code Online (Sandbox Code Playgroud)
返回:
50000
Msg 8152, Level 16, State 10, Line 3
String or binary data would be truncated.
Run Code Online (Sandbox Code Playgroud)
如果要在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));
Run Code Online (Sandbox Code Playgroud)
返回:
50000
40752EB301B41EEAEB309348CE9711D6
0x40752EB301B41EEAEB309348CE9711D6
Run Code Online (Sandbox Code Playgroud)
UPDATE
如果使用VARCHAR(MAX)列或变量但字符数不超过8000个(或者字符数或NVARCHAR(MAX)4000或更少字符的变量),则不会出现问题,一切都会按预期工作:
DECLARE @Test VARCHAR(MAX) = REPLICATE('t', 5000);
SELECT LEN(@Test) AS [Characters],
HASHBYTES('MD5', @Test) AS [MD5];
Run Code Online (Sandbox Code Playgroud)
返回:
5000 0x6ABFBA10B49157F2EF8C85862B6E6313
Run Code Online (Sandbox Code Playgroud)
在SQL Server 2016中,我们不再有HASHBYTES函数的输入参数长度问题。
DECLARE @Test NVARCHAR(MAX);
SET @Test = REPLICATE(CONVERT(NVARCHAR(MAX), N't'), 50000000);
SELECT LEN(@Test);
SELECT HASHBYTES('SHA2_512', @Test);
Run Code Online (Sandbox Code Playgroud)