【问题标题】:Is it possible to Convert a Sqlite Blob column to a HEX string (GUID)?是否可以将 Sqlite Blob 列转换为 HEX 字符串 (GUID)?
【发布时间】:2018-05-13 01:09:54
【问题描述】:

我有一个 SQLite 表,其中有一列将 GUID 存储为字节数组

我正在尝试从我的 SQL 查询中获取 Guid 字符串。 到目前为止,我已经尝试过:

Select BlobGuidColumn from [MyTable]

但这会返回一个blob

是否可以从 SQL 查询中返回 Hex 字符串?

【问题讨论】:

    标签: sql sqlite blob guid


    【解决方案1】:

    接受的答案存在一些问题,但最重要的是它并不总是产生正确的结果。如果目标只是将 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 处都有零。但是当转换不正确时,该组将在一开始就结束:这是一个万无一失的信号,表明您需要在特定情况下使用替代答案。

    【讨论】:

    • 在您所指的文章中,您的“网络字节顺序”是错误的,正如对该文章的评论所指出的那样。你把它固定在那里。同样的错误也感染了现在的答案。也许需要进行编辑?
    【解决方案2】:

    使用来自这个问题的信息: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]
    

    【讨论】:

    • 我发布了一个考虑字节顺序的替代答案。我只是想让您知道,根据您的二进制数据的来源和转换它的原因,如果它最初是由 Windows 软件创建的 GUID,您可能无法获得所需的结果。
    猜你喜欢
    • 1970-01-01
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 2017-09-12
    • 2011-11-01
    • 2020-10-21
    相关资源
    最近更新 更多