【发布时间】: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 让我感到困惑。
【问题讨论】:
-
您是否考虑在 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