【问题标题】:SQL Server Java Compatible GUID / UUID (Big Endian UniqueIdentifier)SQL Server Java 兼容 GUID/UUID(大端唯一标识符)
【发布时间】:2013-03-26 18:06:55
【问题描述】:

我正在尝试将 128 位二进制文​​件转换为与 .net 和 java 中相同的 sql 中的唯一标识符。

我知道 java 使用大端,所以我想以此为基础。

我可以在 .net 中获得正确的字节顺序,但在 SQL Server 中却很难做到。

Java:

        byte[] bytesOfMessage = "google.com".getBytes("UTF-8");

        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] md5 = md.digest(bytesOfMessage);
        ByteBuffer bb = ByteBuffer.wrap(md5);
        LongBuffer ig = bb.asLongBuffer();
        return new UUID(ig.get(0), ig.get(1));

返回 1d5920f4-b44b-27a8-02bd-77c4f0536f5a

.Net

    System.Security.Cryptography.MD5 c = System.Security.Cryptography.MD5.Create();
    byte[] b = c.ComputeHash(Encoding.UTF8.GetBytes("google.com"));
    int z = System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt32(b, 0));
    short y = System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt16(b, 4));
    short x = System.Net.IPAddress.HostToNetworkOrder(BitConverter.ToInt16(b, 6));
    Guid g = new Guid(z, y, x, b.Skip(8).ToArray());
    return g;

返回 1d5920f4-b44b-27a8-02bd-77c4f0536f5a

SQL

DECLARE @s VARCHAR(MAX) = 'google.com' --'goolge.com'

DECLARE @md5 BINARY(16) = HASHBYTES
        (
            'MD5',
            @s
        )

DECLARE @a BINARY(4) = 
        CONVERT
        (
            BINARY(4),
            REVERSE
            (
                CONVERT
                (
                    BINARY(4),
                    LEFT(@md5, 4)
                )
            )
        )

DECLARE @b BINARY(2) = 
        CONVERT
        (
            BINARY(2),
            REVERSE
            (
                CONVERT
                (
                    BINARY(2),
                    RIGHT(@md5, 12)
                )
            )
        )

DECLARE @c BINARY(2) = 
        CONVERT
        (
            BINARY(2),
            REVERSE
            (
                CONVERT
                (
                    BINARY(2),
                    RIGHT(@md5, 10)
                )
            )
        )

DECLARE @d BINARY(8) = 
        CONVERT
        (
            BINARY(8),
            RIGHT(@md5, 8)
        )

SELECT  
    CONVERT
    (
        UNIQUEIDENTIFIER,
        @a + @b + @c + @d
    )

返回 D86B5A7F-7A25-4895-A6D0-63BA3A706627

在转换为 int64 时,我能够让这三个都产生相同的值,但 GUID 让我感到困惑。

Original Issue

Original Answer

【问题讨论】:

  • 您是否考虑在 SQL Server 中编写 .Net CLR 函数?
  • 不要挑剔,但是为什么你的SQL显示:DECLARE @s VARCHAR(MAX) = 'goolge.com'而不是DECLARE @s VARCHAR(MAX) = 'google.com'?
  • 还有一个问题:您确定使用 VARCHAR 数据类型将字符串编码为与您在 Java 和 .NET 中使用的 UTF-8 编码相同的字节吗?也许您可以先检查中间结果,即 .NET 和 sql server 的起始字符串字节相同(在创建 MD5 哈希之前)。
  • 很好地抓住山姆。我检查了一切,除了明显的。现在所有三个示例都返回相同的内容。散了吧!

标签: java .net sql-server uniqueidentifier endianness


【解决方案1】:

如果您在 SQL 示例中更正了 google 的拼写(在您的帖子中为 goolge),您将得到正确的结果。

【讨论】:

    【解决方案2】:

    SQL Server 不支持 UTF-8 编码。见Description of storing UTF-8 data in SQL Server。使用 Michael Harmon 的建议将您的 .NET 函数添加到 SQLServer 以进行转换。有关如何将 .NET 函数添加到 SQLServer 的说明,请参阅 How to encode...。

    或者,不要在 Java 和 .NET 代码中指定 UTF-8。我相信 SQL Server 会像 Java 和 .NET 一样对 varchar 使用相同的 256 位编码。 (但不完全确定。)

    【讨论】:

    • UTF-8 是我的 SQL Server 实例的默认值。如果您的实例不同,则需要相应地修改 java/.net 代码。
    猜你喜欢
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多