sql-server-2008 – SQL Server 2008和HashBytes

我有一个很大的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

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...