我有一个很大的nvarchar,我希望传递给HashBytes函数.
我得到错误:
我得到错误:
“String or binary would be truncated.
Cannot insert the value NULL into
column ‘colname’,tbale ‘table’;
column does not allow nulls. UPDATE
fails. The statement has been
terminated.”
尽管如此,我发现这是由于HashBytes函数的最大限制为8000字节.进一步的搜索显示了我的一个“解决方案”,其中我的大varchar将被分开和散列,然后再结合这个用户定义的功能:
function [dbo].[udfLargeHashTable] (@algorithm nvarchar(4),@InputDataString varchar(MAX)) RETURNS varbinary(MAX) AS BEGIN DECLARE @Index int,@InputDataLength int,@ReturnSum varbinary(max),@InputData varbinary(max) SET @ReturnSum = 0 SET @Index = 1 SET @InputData = convert(binary,@InputDataString) SET @InputDataLength = DATALENGTH(@InputData) WHILE @Index <= @InputDataLength BEGIN SET @ReturnSum = @ReturnSum + HASHBYTES(@algorithm,SUBSTRING(@InputData,@Index,8000)) SET @Index = @Index + 8000 END RETURN @ReturnSum END
我打电话给:
set @ReportDefinitionHash=convert(int,dbo.[udfLargeHashTable]('SHA1',@ReportDefinitionForLookup))
@ReportDefinitionHash是int,而@ReportDefinitionForLookup是varchar
传递像’test’这样的简单的字符会产生一个与UDF不同的int,而不是HashBytes的正常调用.
关于这个问题的任何建议?
解决方法
只需使用此功能(取自
Hashing large data strings with a User Defined Function):
create function dbo.fn_hashbytesMAX ( @string nvarchar(max),@Algo varchar(10) ) returns varbinary(20) as /************************************************************ * * Author: Brandon Galderisi * Last modified: 15-SEP-2009 (by Denis) * Purpose: uses the system function hashbytes as well * as sys.fn_varbintohexstr to split an * nvarchar(max) string and hash in 8000 byte * chunks hashing each 8000 byte chunk,* getting the 40 byte output,streaming each * 40 byte output into a string then hashing * that string. * *************************************************************/ begin declare @concat nvarchar(max),@NumHash int,@HASH varbinary(20) set @NumHash = ceiling((datalength(@string)/2)/(4000.0)) /* HashBytes only supports 8000 bytes so split the string if it is larger */ if @NumHash>1 begin -- # * 4000 character strings ;with a as (select 1 as n union all select 1) -- 2,b as (select 1 as n from a,a a1) -- 4,c as (select 1 as n from b,b b1) -- 16,d as (select 1 as n from c,c c1) -- 256,e as (select 1 as n from d,d d1) -- 65,536,f as (select 1 as n from e,e e1) -- 4,294,967,296 = 17+ TRILLION characters,factored as (select row_number() over (order by n) rn from f),factors as (select rn,(rn*4000)+1 factor from factored) select @concat = cast(( select right(sys.fn_varbintohexstr ( hashbytes(@Algo,substring(@string,factor - 4000,4000)) ),40) + '' from Factors where rn <= @NumHash for xml path('') ) as nvarchar(max)) set @HASH = dbo.fn_hashbytesMAX(@concat,@Algo) end else begin set @HASH = convert(varbinary(20),hashbytes(@Algo,@string)) end return @HASH end
结果如下:
select hashbytes('sha1',N'test') --native function with nvarchar input,hashbytes('sha1','test') --native function with varchar input,dbo.fn_hashbytesMAX('test','sha1') --Galderisi's function which casts to nvarchar input,dbo.fnGetHash('sha1','test') --your function
输出:
0x87F8ED9157125FFC4DA9E06A7B8011AD80A53FE1 0xA94A8FE5CCB19BA61C4C0873D391E987982FBBD3 0x87F8ED9157125FFC4DA9E06A7B8011AD80A53FE1 0x00000000AE6DBA4E0F767D06A97038B0C24ED720662ED9F1