如何从 MySQL/MariaDB 中的二进制列格式化 uuid 字符串
Posted
技术标签:
【中文标题】如何从 MySQL/MariaDB 中的二进制列格式化 uuid 字符串【英文标题】:How to format uuid string from binary column in MySQL/MariaDB 【发布时间】:2016-09-07 05:14:33 【问题描述】:在 mysql/MariaDB 中,存储 uuid 的最有效方式是在 BINARY(16) 列中。但是,有时您希望将其作为格式化的 uuid 字符串获取。
给定以下表格结构,我如何以默认格式获取所有 uuid?
CREATE TABLE foo (uuid BINARY(16));
【问题讨论】:
见my uuid blog 【参考方案1】:以下将创建我所追求的结果:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
FROM foo;
【讨论】:
查看 Oleg Mikheev 的回答,现在使用 BIN_TO_UUID() 在 mysql 8.0 中更容易做到 是的,如果您使用的是 MySQL 8.0,请不要再使用此答案。使用下面的 Oleg。 优化:与其将完整的HEX(uuid)
操作重复5次,不如先SET @hex = (SELECT LOWER(HEX(bytes)));
,再引用@hex
5次,也跳过封闭的LOWER() ?【参考方案2】:
这是使用 concat_ws 的替代方法
将原始 uuid 存储在变量 @x 中
SELECT @x := hex(uuid)
FROM foo;
使用 CONCAT_WS 和 SUBSTR 解析人类可读的 UUID
SELECT
LOWER(CONCAT_WS('-',
SUBSTR(@x, 1, 8),
SUBSTR(@x, 9, 4),
SUBSTR(@x, 13, 4),
SUBSTR(@x, 17, 4),
SUBSTR(@x, 21)
)) AS uuid;
【讨论】:
这里还有另一种替代方法:***.com/questions/27039152/…【参考方案3】:MySQL 8 新增two new UUID functions:
UUID_TO_BIN BIN_TO_UUID - 这就是你要找的人所以:
SELECT BIN_TO_UUID(uuid) FROM foo
【讨论】:
我想知道你是否可以BIN_TO_UUID(<fieldName>)
,这证实了这一点。虽然,如果您必须这样做,您可能会将true
标志传递给UUID_TO_BIN
,因此您还需要它获取正确的 UUID。 IE。 BIN_TO_UUID( <fieldName>, true )
我收到“功能不存在”,我有最新版本【参考方案4】:
在早期(8 之前)版本中,您可以在 MySQL 中创建function,如下所示:
CREATE
FUNCTION uuid_of(uuid BINARY(16))
RETURNS VARCHAR(36)
RETURN LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
));
然后在您的查询中简单地使用它:
SELECT
uuid_of(id)
name,
age
FROM users
它会产生:
(c6f5703b-fec2-43fd-8f45-45f06583d450, Some name, 20)
【讨论】:
很抱歉,这个计算是错误的,它没有反映原始 UUID。在 MySQL Workbench 中查询时 UUID2e9660c2-1e51-4b9e-9a86-6db1a2770422
显示为 c260962e-511e-9e4b-9a86-6db1a2770422
@Alex.H 有没有复制? SELECT hex(uuid_column) FROM $table
然后SELECT uuid_of(uuid_column) FROM $table
?
hex(myId)
和 uuid_of(uuid_column)
实际上是相同的 C260962E511E9E4B9A866DB1A2770422
和 c260962e-511e-9e4b-9a86-6db1a2770422
,但它不是我的 MVC 应用程序生成并保存到数据库的 ID(我相信)。它生成2E9660C2-1E51-4B9E-9A86-6DB1A2770422
,保存为C260962E511E9E4B9A866DB1A2770422
。这可能是我正在使用的 MySQL EF 适配器的问题,因为如果我使用来自 uuid_of
的 UUID 查询任何内容,我什么也得不到,但如果我使用上面发布的函数中的那个,我会获取我的记录。【参考方案5】:
正确的结果是由下面的脚本生成的,其他脚本生成了一个 UUID 但不是正确的。
CONCAT(
substr(hex(Id), 7, 2), substr(hex(Id), 5, 2), substr(hex(Id), 3, 2), substr(hex(Id), 1, 2), '-'
, substr(hex(Id), 11, 2) , substr(hex(Id), 9, 2) , '-'
, substr(hex(Id), 15, 2) , substr(hex(Id), 13, 2) , '-'
, substr(hex(Id), 17, 4) , '-'
, substr(hex(Id), 21, 12)
)
运行其他脚本的结果生成了错误的 UUID,如下所示:
预期的 UUID -2e9660c2-1e51-4b9e-9a86-6db1a2770422
生成了什么 - c260962e-511e-9e4b-9a86-6db1a2770422
如您所见,它们是不同的。
【讨论】:
【参考方案6】:如果您正在寻找相反的东西,即如何从字符串转换为二进制,也许是为了进行连接或其他事情,这里介绍了这一点:Convert UUID to/from binary in Node
在 Mysql 5.7 上运行的这段 SQL 帮助我锁定了这个概念:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 1, 8), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 9, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 13, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 17, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 21)
))
输出是43d597d7-2323-325a-90fc-21fa5947b9f3
。
字符串 -> 二进制
所以UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))
在INSERT
/ UPDATE
/ JOIN
/ SELECT
期间将 UUID 转换为二进制,并且
二进制 -> 字符串
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
【讨论】:
谢谢老兄,我每周复制粘贴多次 xaxa。【参考方案7】:根据这张 Jira 票 https://jira.mariadb.org/browse/MDEV-15854UUID_TO_BIN 和 BIN_TO_UUID 没有进入 Mariadb 服务器版本 10.5。如果您使用的是这个版本并且在 Mariadb Server 下,您将不得不使用上面提到的自定义实现。
【讨论】:
以上是关于如何从 MySQL/MariaDB 中的二进制列格式化 uuid 字符串的主要内容,如果未能解决你的问题,请参考以下文章
数据库MySQL/mariadb知识点——日志记录二进制日志