SQL Server 2014 nvarchar(max)结果的Hashbytes是nvarchar(max)

时间:2016-07-30 04:10:48

标签: sql-server hashbytes

使用SQL Server 2014我有一个名为nvarchar(max)的{​​{1}}列的表,它可以包含许多K的ASCII文本文件。然后,我希望在该文件上执行MD5哈希字节,并且结果哈希值应始终为20个字节。

当我选择[ASCII File]时,我的查询已完成并出现错误

  

Msg 8152,Level 16,State 10,Line 4
  字符串或二进制数据将被截断。

我尝试

时收到相同的消息
hashbytes('MD5', [ASCII File])

我尝试

时收到相同的消息
left(hashbytes('MD5', [ASCII File]), 50)

似乎自从我正在进行哈希字节的列convert(varchar(50), hashbytes('MD5', [ASCII File])) 以来,哈希字节函数的结果也是nvarchar(max)

你能告诉我如何才能让结果成为预期的20长而不是这么长时间它必须被截断吗?

4 个答案:

答案 0 :(得分:8)

  

似乎自从我正在进行哈希字节的字段是nvarchar(max)时,hashbytes的结果是nvarchar(max)。

不,这是不可能的,特别是因为HASHBYTES的返回值是VARBINARY。此外,由于您的测试只是SELECT语句而不是INSERT语句,因此返回值无法获得截断错误。截断错误来自输入值。正如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

答案 1 :(得分:4)

在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);

HASHBYTES (Transact-SQL)

答案 2 :(得分:1)

2016年sql中删除了HASHBYTES(Transact-SQL)函数的输入长度限制为8,000字节

基于以下算法的是输出数据大小 MD2,MD4和MD5为128位(16字节); SHA和SHA1为160位(20字节); SHA2_256为256位(32字节) SHA2_512为512位(64字节)。

答案 3 :(得分:1)

如果您正在尝试在sql中转换大型varbinary或图像文件,则有一些内置函数可以执行此操作(可能从2014年开始),此简单函数将同时适用于varbinary(max)和较旧的Image字段。

/****** Object:  UserDefinedFunction [dbo].[MD5Bin]    Script Date: 16/07/2018 11:04:26 ******/

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

-- ==================================================
-- Author:    Darren Steven
-- Create date: 16/07/2018
-- Description: Hashes a binary or image field with MD5
-- ==================================================
CREATE FUNCTION [dbo].[MD5Bin](@value varbinary(max))
RETURNS varchar(32)
AS
BEGIN
  RETURN SUBSTRING(master.sys.fn_sqlvarbasetostr(master.sys.fn_repl_hash_binary(@value)),3,32);
END
GO

然后只需选择以下内容即可调用该函数:

SELECT dbo.MD5Bin(imageFieldName) from dbo.yourTable