我已经采取接受的答案,并与修改后的有点以下改进:
- 不再递归函数
- 现在绑定到架构
- 不再依靠无证ST已编程的程序
- 两个版本:一个用于nvarchar,一个用于varchar
- 返回与HASHBYTES相同的数据大小,由最终用户根据所用算法将其转换为较小值。这使得这些功能可以支持未来的算法和更大的数据返回。
随着这些变化,的功能,现在可以在持久性计算列作为创建时它们现在标记确定性被使用。
CREATE FUNCTION dbo.fnHashBytesNVARCHARMAX
(
@Algorithm VARCHAR(10),
@Text NVARCHAR(MAX)
)
RETURNS VARBINARY(8000)
WITH SCHEMABINDING
AS
BEGIN
DECLARE @NumHash INT;
DECLARE @HASH VARBINARY(8000);
SET @NumHash = CEILING(DATALENGTH(@Text)/(8000.0));
/* HashBytes only supports 8000 bytes so split the string if it is larger */
WHILE @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 @Text = CAST
(
(
SELECT CONVERT(VARCHAR(MAX), HASHBYTES(@Algorithm, SUBSTRING(@Text, factor - 4000, 4000)), 1)
FROM factors
WHERE rn <= @NumHash
FOR XML PATH('')
) AS NVARCHAR(MAX)
);
SET @NumHash = CEILING(DATALENGTH(@Text)/(8000.0));
END;
SET @HASH = CONVERT(VARBINARY(8000), HASHBYTES(@Algorithm, @Text));
RETURN @HASH;
END;
CREATE FUNCTION dbo.fnHashBytesVARCHARMAX
(
@Algorithm VARCHAR(10),
@Text VARCHAR(MAX)
)
RETURNS VARBINARY(8000)
WITH SCHEMABINDING
AS
BEGIN
DECLARE @NumHash INT;
DECLARE @HASH VARBINARY(8000);
SET @NumHash = CEILING(DATALENGTH(@Text)/(8000.0));
/* HashBytes only supports 8000 bytes so split the string if it is larger */
WHILE @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 * 8000) + 1 factor FROM factored)
SELECT @Text = CAST
(
(
SELECT CONVERT(VARCHAR(MAX), HASHBYTES(@Algorithm, SUBSTRING(@Text, factor - 8000, 8000)), 1)
FROM factors
WHERE rn <= @NumHash
FOR XML PATH('')
) AS NVARCHAR(MAX)
);
SET @NumHash = CEILING(DATALENGTH(@Text)/(8000.0));
END;
SET @HASH = CONVERT(VARBINARY(8000), HASHBYTES(@Algorithm, @Text));
RETURN @HASH;
END;
基本上,你不想聚合你的哈希字符串,所以返回类型应该是varbinary(20)。然后,尝试运行以下命令:'select hashbytes('sha1','test'),hashbytes('sha1',N'test')'(您非常惊喜):) – 2010-09-15 14:52:04