nic*_*dnk 24 mysql binary uuid
我不明白为什么
SELECT UUID();
Run Code Online (Sandbox Code Playgroud)
返回类似于:
3f06af63-a93c-11e4-9797-00505690773f
Run Code Online (Sandbox Code Playgroud)
但是如果我将它插入二进制(16)字段(UUID()函数)并使用例如BEFORE INSERT触发器并运行select,它将返回如下内容:
0782ef48-a439-11
Run Code Online (Sandbox Code Playgroud)
请注意,这两个UUID不是相同的数据.
我意识到二进制文件和一个UUID字符串看起来不一样,但是所选数据不应该只有那么长吗?否则,它怎么可能同样具有独特性呢?
将它存储为char(36)更好吗?我只需要它是唯一的,以防止重复插入.它永远不会被选中或用于连接.
编辑:
在触发之前会是这样的:
BEGIN
if NEW.UUID IS NULL THEN
NEW.UUID = UUID();
END IF
END
Run Code Online (Sandbox Code Playgroud)
nic*_*dnk 64
所以,作为对评论的回应.将36-char UUID存储为二进制(16)的正确方法是以下列方式执行插入:
INSERT INTO sometable (UUID) VALUES
(UNHEX(REPLACE("3f06af63-a93c-11e4-9797-00505690773f", "-","")))
Run Code Online (Sandbox Code Playgroud)
UNHEX因为UUID已经是一个hexed值.我们修剪(REPLACE)语句中的破折号,使长度减少到32个ASCII字符(我们的16个字节表示为HEX).显然,您可以在存储之前随时执行此操作,因此不必由数据库处理.
您可以像这样检索UUID:
SELECT HEX(UUID) FROM sometable;
Run Code Online (Sandbox Code Playgroud)
以防万一有人遇到这个帖子并且不确定这是如何工作的.
请记住:如果您使用UUID选择一行,请使用UNHEX()以下条件:
SELECT * FROM sometable WHERE UUID = UNHEX('3f06af63a93c11e4979700505690773f');
Run Code Online (Sandbox Code Playgroud)
而不是HEX()专栏:
SELECT * FROM sometable WHERE HEX(UUID) = '3f06af63a93c11e4979700505690773f';
Run Code Online (Sandbox Code Playgroud)
第二种解决方案虽然有效,但要求MySQL HEX确定所有UUID,然后才能确定哪些行匹配.这是非常低效的.
编辑:如果你正在使用MySQL 8,你应该看看SlyDave的答案中提到的UUID函数.这个答案仍然是正确的,但它没有优化UUID索引,这些索引可以使用这些函数本机完成.
Sly*_*ave 24
从MySQL 8开始,您可以使用两个新的UUID函数:
BIN_TO_UUID
SELECT BIN_TO_UUID(uuid, true) AS uuid FROM foo;
-- 3f06af63-a93c-11e4-9797-00505690773f
Run Code Online (Sandbox Code Playgroud)UUID_TO_BIN
INSERT INTO foo (uuid) VALUES (UUID_TO_BIN('3f06af63-a93c-11e4-9797-00505690773f', true));
Run Code Online (Sandbox Code Playgroud)此方法还支持重新排列uuid的时间组件以增强索引性能(通过按时间顺序排序),只需将第二个参数设置为true - 这仅适用于UUID1.
如果使用trueon UUID_TO_BIN标志来建立索引性能(推荐),则还必须将其设置为on,BIN_TO_UUID否则将无法正确转换.
有关详细信息,请参阅文档.
Dev*_*von 16
使用 swap_flag 参数填充 MySQL 5 的 BIN_TO_UUID 和 UUID_TO_BIN。
DELIMITER $$
CREATE FUNCTION BIN_TO_UUID(b BINARY(16), f BOOLEAN)
RETURNS CHAR(36)
DETERMINISTIC
BEGIN
DECLARE hexStr CHAR(32);
SET hexStr = HEX(b);
RETURN LOWER(CONCAT(
IF(f,SUBSTR(hexStr, 9, 8),SUBSTR(hexStr, 1, 8)), '-',
IF(f,SUBSTR(hexStr, 5, 4),SUBSTR(hexStr, 9, 4)), '-',
IF(f,SUBSTR(hexStr, 1, 4),SUBSTR(hexStr, 13, 4)), '-',
SUBSTR(hexStr, 17, 4), '-',
SUBSTR(hexStr, 21)
));
END$$
CREATE FUNCTION UUID_TO_BIN(uuid CHAR(36), f BOOLEAN)
RETURNS BINARY(16)
DETERMINISTIC
BEGIN
RETURN UNHEX(CONCAT(
IF(f,SUBSTRING(uuid, 15, 4),SUBSTRING(uuid, 1, 8)),
SUBSTRING(uuid, 10, 4),
IF(f,SUBSTRING(uuid, 1, 8),SUBSTRING(uuid, 15, 4)),
SUBSTRING(uuid, 20, 4),
SUBSTRING(uuid, 25))
);
END$$
DELIMITER ;
--
-- Tests to demonstrate that it works correctly. These are the values taken from
-- https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid-to-bin
--
-- If you run these SELECTs using the above functions, the
-- output of the two columns should be exactly identical in all four cases.
SET @uuid = '6ccd780c-baba-1026-9564-5b8c656024db';
SELECT HEX(UUID_TO_BIN(@uuid, 0)), '6CCD780CBABA102695645B8C656024DB';
SELECT HEX(UUID_TO_BIN(@uuid, 1)), '1026BABA6CCD780C95645B8C656024DB';
SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,0),0), '6ccd780c-baba-1026-9564-5b8c656024db';
SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid,1),1), '6ccd780c-baba-1026-9564-5b8c656024db';
Run Code Online (Sandbox Code Playgroud)
包括来自https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_uuid-to-bin的 SELECT 示例,这些示例表明上述代码返回与 8.0 函数完全相同的结果. 这些函数被认为是确定性的,因为它们总是为给定的输入产生相同的输出。见https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html
其他答案是正确的。该UUID()函数返回一个36个字符串,需要使用所示函数进行转换(UNHEX()或在较新的平台上UUID_TO_BIN())。
但是,如果您使用自己的软件来创建UUID,则可以改用十六进制立即数表示法。
因此,我将在MySQL UUID()函数中使用以下代码:
INSERT INTO sometable (id) VALUES (UNHEX(REPLACE(UUID(), '-', ''))); -- all versions
INSERT INTO sometable (id) VALUES (UUID_TO_BIN(UUID()); -- since v8.0
Run Code Online (Sandbox Code Playgroud)
但是在我生成自己的UUID的情况下使用此方法;
INSERT INTO sometable (id) VALUES 0x3f06af63a93c11e4979700505690773f;
Run Code Online (Sandbox Code Playgroud)
同样,您可以在WHERE子句中使用十六进制文字:
SELECT * FROM sometable WHERE id = 0x3f06af63a93c11e4979700505690773f;
Run Code Online (Sandbox Code Playgroud)
如果您不必每次都将数据转换为UUID字符串,则速度会更快。
注意:'x'in '0xaBc区分大小写。但是,十六进制数字不是。
我正在使用MariaDB,因此BIN_TO_UUID功能族不存在。无论如何,我设法获得了相应的值。
bin -> hex
这里uuid是uuid的binary(16)值;您将使用下面的值选择它的可读版本。
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)
))
Run Code Online (Sandbox Code Playgroud)
hex -> bin
这cc6e6d97-5501-11e7-b2cb-ceedca613421是UUID的可读版本,您将在WHERE子句中使用下面的值来寻找它。
UNHEX(REPLACE('cc6e6d97-5501-11e7-b2cb-ceedca613421', '-', ''))
Run Code Online (Sandbox Code Playgroud)
干杯