【发布时间】:2018-05-13 01:09:54
【问题描述】:
我有一个 SQLite 表,其中有一列将 GUID 存储为字节数组
我正在尝试从我的 SQL 查询中获取 Guid 字符串。 到目前为止,我已经尝试过:
Select BlobGuidColumn from [MyTable]
但这会返回一个blob 列
是否可以从 SQL 查询中返回 Hex 字符串?
【问题讨论】:
我有一个 SQLite 表,其中有一列将 GUID 存储为字节数组
我正在尝试从我的 SQL 查询中获取 Guid 字符串。 到目前为止,我已经尝试过:
Select BlobGuidColumn from [MyTable]
但这会返回一个blob 列
是否可以从 SQL 查询中返回 Hex 字符串?
【问题讨论】:
接受的答案存在一些问题,但最重要的是它并不总是产生正确的结果。如果目标只是将 128 位从二进制映射到类似 GUID (8-4-4-4-12) 的表示形式,那么它就可以了。但是,如果您确实希望某些东西评估为相同的 GUID,则不会这样做,因为没有考虑基础数据的字节序。
以下面的guid为例:
BC7CAE8C-E4D7-49CA-86E4-5FD540106CC0
表示为字节数组,不一定得到
BC-7C-AE-8C-E4-D7-49-CA-86-E4-5F-D5-40-10-6C-C0
作为答案,因为 GUID/UUID 的内部表示是依赖于相关 UUID 变体的字节顺序。 Variant 1 UUID 是严格的网络字节顺序(小端),而 Variant 2 UUID 在各方面都是相同的,除了一半的分组以大端字节顺序存储在内存中(或数据库中的磁盘上),而另一半是按网络字节顺序排列的。
我写了一篇很长的文章,深入探讨了 UUID/GUID 的历史以及这两个变体之间的区别,并提供了将 UUID 从二进制转换为文本的说明:Converting a binary/blob guid column to text in SQL: it's a lot harder than you think。
根据所讨论的变体,您可以直接使用 SQL HEX() 函数 as in the currently accepted answer:
SELECT substr(hex(guid), 1, 8)
|| '-' || substr(hex(guid), 9, 4)
|| '-' || substr(hex(guid), 13, 4)
|| '-' || substr(hex(guid), 17, 4)
|| '-' || substr(hex(guid), 21, 12)
FROM [MyTable]
或者,如果源数据来自 Microsoft 世界(例如 COM/WIN32/.NET 应用程序),您将需要使用这种更为复杂的方法,它为每个分组考虑适当的字节顺序:
SELECT
substr(hguid, 7, 2) || substr(hguid, 5, 2) || substr(hguid, 3, 2) || substr(hguid, 1, 2) || '-'
|| substr(hguid, 11, 2) || substr(hguid, 9, 2) || '-'
|| substr(hguid, 15, 2) || substr(hguid, 13, 2) || '-'
|| substr(hguid, 17, 4) || '-'
|| substr(hguid, 21, 12)
AS guid
FROM (SELECT hex(guid) AS hguid FROM messages)
(这里 guid 列在最后一行只转换为十六进制一次,以避免对每个字节重复这样做的开销。)
我实际上并不清楚(如在 OP 的特定场景中)Microsoft SQL Server 是否以网络字节顺序或(部分)大端顺序将 GUID 存储在磁盘上,尽管我倾向于认为是后者考虑到微软技术在其他任何地方都是如此(这不是一个通用规则,但总的来说,“guid”意味着 Little Endian,而“uuid”意味着 Big -- see the article 了解更多信息)。
提示:如果结果以零开头,则说明您做错了。给定 UUIDv1/UUIDv2(时间戳)中第一组的源,许多分辨率有限的源在第一组十六进制数字的 end 处都有零。但是当转换不正确时,该组将在一开始就结束:这是一个万无一失的信号,表明您需要在特定情况下使用替代答案。
【讨论】:
使用来自这个问题的信息:Sqlite: How to cast(data as TEXT) for BLOB 还有这个问题:Convert varchar to uniqueidentifier in SQL Server
我得到了答案:
SELECT substr(hex(BlobGuidColumn), 1, 8) || '-' || substr(hex(BlobGuidColumn), 9, 4) || '-' || substr(hex(BlobGuidColumn), 13, 4) || '-' || substr(hex(BlobGuidColumn), 17, 4) || '-' || substr(hex(BlobGuidColumn), 21, 12) FROM [MyTable]
【讨论】: