3

I'm trying to get the equivalent int value of guid.getHashCode() in SQL Server 2008. I've tried CHECKSUM(uniqueidentifier var) but it does not return the same value. Is it possible to get the HashCode value of a guid in SQL Server?

For example

Guid guid = new Guid("A0AE0446-3C50-479A-A909-3BA9C711007E"); 
int hash = guid.GetHashCode();, 

returns -1476508766, is it possible to get the same value in sql server?

4

2 回答 2

7

为此,您需要知道如何Guid.GetHashCode()计算值。使用 DotPeek:

public override int GetHashCode()
{
  return this._a ^ ((int) this._b << 16 | (int) (ushort) this._c) ^ ((int) this._f << 24 | (int) this._k);
}

其中私有变量保存的值Guid和声明为:

private int _a;
private short _b;
private short _c;
private byte _d;
private byte _e;
private byte _f;
private byte _g;
private byte _h;
private byte _i;
private byte _j;
private byte _k;

实现为 T-SQL 函数:

create function dbo.GetDotNetHashCode(@guid uniqueidentifier)
returns int
as
begin

    -- calculates a hash code value equivalent to .NETs Guid.GetHashCode() method

    declare @bytes binary(16) = cast(@guid as binary(16)),
            @hashCode int

    -- when converting to binary, the byte order of the first 3 segments is reversed

    declare @_a int = convert(int, 
                            substring(@bytes, 4, 1) + 
                            substring(@bytes, 3, 1) + 
                            substring(@bytes, 2, 1) + 
                            substring(@bytes, 1, 1))

    declare @_b int = convert(smallint, 
                            substring(@bytes, 6, 1) + 
                            substring(@bytes, 5, 1))

    declare @_c int = convert(int, 
                            substring(@bytes, 8, 1) + 
                            substring(@bytes, 7, 1))

    declare @_f int = convert(int, substring(@bytes, 11, 1))
    declare @_k int = convert(int, substring(@bytes, 16, 1))

    -- shift @_b using a bigint to avoid overflow
    -- left shift 16 is equivalent to multiplying by 2^16

    declare @_b_shift bigint = cast(@_b as bigint) * 65536
    set @_b = convert(int, substring(cast(@_b_shift as varbinary(8)), 5, 4))

    -- shift @_f using a bigin to avoid overflow
    -- left shift 24 is equivalent to multiplying by 2^24

    declare @_f_shift bigint = cast(@_f as bigint) * 16777216
    set @_f = convert(int, substring(cast(@_f_shift as varbinary(8)), 5, 4))

    set @hashCode = @_a ^ (@_b | @_c) ^ (@_f | @_k)

    return @hashCode

end

并使用以下内容进行测试(评论具有来自调用的预期值Guid.GetHashCode()):

/*

aeee939b-d2c8-4411-9cf9-94ab520e3c1c : -400107626
88ed5159-7900-4530-9886-841b7d42665b : 1978471474
2910ba35-ab2f-42a5-aed1-ea710d25a42e : 1749022910
0430b8b0-981b-4f1a-82fb-afe0725e8fd3 :  858519417
ba8cd9e4-fa1d-4ead-9145-b830aea6a641 : -124676344
9d5b5203-a2d4-4b8e-86dd-7eb5e4250960 : 1099897325
28b88e48-acc4-4f74-be28-4fcb92ad8c55 : -881016471
892056e9-dde1-4999-92ba-6c74b4a583c2 :  952180658
f0c3d3b5-bffc-4bda-b45a-70825f33b01f : 1061132400
df218e55-d672-48aa-b105-47578869068d : 1314113138

*/

declare @test table (Guid uniqueidentifier)

insert @test values
    ('aeee939b-d2c8-4411-9cf9-94ab520e3c1c'),
    ('88ed5159-7900-4530-9886-841b7d42665b'),
    ('2910ba35-ab2f-42a5-aed1-ea710d25a42e'),
    ('0430b8b0-981b-4f1a-82fb-afe0725e8fd3'),
    ('ba8cd9e4-fa1d-4ead-9145-b830aea6a641'),
    ('9d5b5203-a2d4-4b8e-86dd-7eb5e4250960'),
    ('28b88e48-acc4-4f74-be28-4fcb92ad8c55'),
    ('892056e9-dde1-4999-92ba-6c74b4a583c2'),
    ('f0c3d3b5-bffc-4bda-b45a-70825f33b01f'),
    ('df218e55-d672-48aa-b105-47578869068d')

select Guid, dbo.GetDotNetHashCode(Guid) as HashCode from @test

注意:这是在 SQL Server 2012 中测试过的,但我相信它在 2008 年也可以使用。

于 2013-07-09T16:09:00.163 回答
-1
SELECT HASHBYTES('MD5',CAST(variable AS VARBINARY(MAX)))

sql-server 中的哈希码

于 2013-07-09T14:07:02.057 回答