在T-SQL中为字符串实现GetHashCode

时间:2013-09-26 09:44:03

标签: c# sql sql-server tsql common-table-expression

我想在T-SQL中创建一个类似于Java中的标量函数。

命令式语言的标准实现是:

int hash = 0;
for (int i = 0; i < length; i++)
{
    hash = 31*hash + value[i];
}
return hash;

我在tsql中实现这一点并不是那么好,而且从我的POV编写t-sql中的命令式代码是应该避免的。我想这可以用CTE完成吗?请=)

另外,我可以使它始终是positivie,即当结果超过integrer max时,它会流过0而不是整数min吗?让我们假设可能的参数数量(我的解决方案中特殊类的数量)并不是很大。假设它永远不会超过1000,所以我确信即使使用uint也可以避免碰撞。


PS:如果有人对我需要的东西感兴趣,那么我可以解释一下,可能你可以建议一个更好的解决方案。我有一个包含integer标识列和varchar'TypeFullName'的表格 - 这是我们C#解决方案中类的全名。

我需要编写一个脚本,将手动设置ID作为TypeFullName的函数依赖(是的,打开SET IDENTITY INSERT选项)。如果我知道类型名称,那么我可以计算ID。我知道这听起来像一个设计糟糕的系统,它可能是,但相信我,我现在必须这样做)

谢谢!

2 个答案:

答案 0 :(得分:1)

阅读关于CheckSum与Hashbytes的文章。 (http://craftydba.com/?p=3005

它们是两个内置的SQL Server函数,它们将为您生成给定值的哈希键。一个比另一个更独特。

如果您仍有疑问,请询问。

此致

约翰

www.craftydba.com

PS:

在转换为int或big int时,您正在失去精度。只需将其保存为GUID(16字节十六进制)。

enter image description here

答案 1 :(得分:0)

我在internet找到了一个解决方案,稍微更新了一下,将输出限制为正数:

begin
declare @h bigint
set @h = 0
select @h = (@h*31 + ascii(substring(@str,X.pos,1)))%4294967296
   from (select top(len(@str)) 
             row_number() over (order by getdate()) as pos 
           from sys.all_objects) as X
if @h >= 2147483647 set @h = @h - 2147483647
return convert(int, @h)
end;

select top from sys.all_objects真的很骇客,但是(((至少它有效。