插入和选择UUID为二进制(16)

时间:2015-01-31 11:36:00

标签: mysql binary uuid

我不明白为什么

SELECT UUID();

返回类似的内容:

3f06af63-a93c-11e4-9797-00505690773f

但是如果我将它插入二进制(16)字段(UUID()函数)并使用例如BEFORE INSERT触发器并运行select,它将返回如下内容:

0782ef48-a439-11

请注意,这两个UUID不是相同的数据。

我意识到二进制文件和一个UUID字符串看起来不一样,但是所选数据不应该同样长吗?否则,它怎么可能同样具有独特性?

将它存储为char(36)更好吗?我只需要它是唯一的,以防止重复插入。它永远不会被选中或用于连接。

编辑:

触发之前的

就像:

BEGIN

if NEW.UUID IS NULL THEN

NEW.UUID = UUID();

END IF

END

6 个答案:

答案 0 :(得分:50)

所以,作为对评论的回应。将36-char UUID存储为二进制(16)的正确方法是以下列方式执行插入:

INSERT INTO sometable (UUID) VALUES
       (UNHEX(REPLACE("3f06af63-a93c-11e4-9797-00505690773f", "-","")))

UNHEX因为UUID已经是一个hexed值。我们修剪(REPLACE)语句中的短划线,使长度减少到32个ASCII字符(我们的16个字节表示为HEX)。显然,您可以在存储之前随时执行此操作,因此不必由数据库处理。

您可以像这样检索UUID:

SELECT HEX(UUID) FROM sometable;

以防万一有人遇到这个帖子并且不确定这是如何运作的。

请记住:如果您使用UUID选择行,在条件上使用UNHEX()

SELECT * FROM sometable WHERE UUID = UNHEX('3f06af63a93c11e4979700505690773f');

而不是HEX()列:

SELECT * FROM sometable WHERE HEX(UUID) = '3f06af63a93c11e4979700505690773f';

第二个解决方案虽然有效,但要求MySQL HEX使用所有UUID,然后才能确定哪些行匹配。效率非常低。

编辑:如果你正在使用MySQL 8,你应该看看SlyDave的答案中提到的UUID功能。这个答案仍然是正确的,但它并没有优化UUID索引,这些索引可以使用这些函数本地完成。

答案 1 :(得分:18)

从MySQL 8开始,您可以使用两个新的UUID functions

  • BIN_TO_UUID

    SELECT BIN_TO_UUID(uuid, true) AS uuid FROM foo;
    -- 3f06af63-a93c-11e4-9797-00505690773f
    
  • UUID_TO_BIN

    INSERT INTO foo (uuid) VALUES (UUID_TO_BIN('3f06af63-a93c-11e4-9797-00505690773f', true));
    

此方法还支持重新排列uuid的时间组件以增强索引性能(通过按时间顺序排序),只需将第二个参数设置为true - 这仅适用于UUID1。

如果您使用true UUID_TO_BIN标记来建立索引性能(推荐),则还必须在BIN_TO_UUID上设置它,否则它将无法正常转换。

有关详细信息,请参阅文档。

答案 2 :(得分:4)

我正在使用MariaDB,因此BIN_TO_UUID函数系列不存在。无论如何,我设法得到了相应的值。

bin - >十六进制

这里,uuid是uuid的二进制(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)
))

hex - >仓

这里,cc6e6d97-5501-11e7-b2cb-ceedca613421是UUID的可读版本,您将在WHERE子句中使用下面的值来寻找它。

UNHEX(REPLACE('cc6e6d97-5501-11e7-b2cb-ceedca613421', '-', ''))

干杯

答案 3 :(得分:2)

其他答案是正确的。 UUID()函数返回一个36个字符串,需要使用显示的函数(UNHEX()或在新平台上的UUID_TO_BIN())进行转换。

但是,如果您使用自己的软件来创建UUID,则可以改用Hexadecimal Literal notation

因此,我将对MySQL UUID()函数使用以下内容:

INSERT INTO sometable (id) VALUES (UNHEX(REPLACE(UUID(), '-', '')));  -- all versions
INSERT INTO sometable (id) VALUES (UUID_TO_BIN(UUID());               -- since v8.0

但是如果我生成自己的UUID,请使用它;

INSERT INTO sometable (id) VALUES 0x3f06af63a93c11e4979700505690773f;

类似地,您可以在WHERE子句中使用十六进制文字:

SELECT * FROM sometable WHERE id = 0x3f06af63a93c11e4979700505690773f;

如果您不必每次都将数据转换为UUID字符串,则会更快。

注意:'x'中的'0xaBc区分大小写。但是,十六进制数字不是。

答案 4 :(得分:2)

针对BIN_TO_UUID和针对MySQL 5的UUID_TO_BIN的填充:

DELIMITER $$

CREATE FUNCTION BIN_TO_UUID(b BINARY(16))
RETURNS CHAR(36)
BEGIN
   DECLARE hexStr CHAR(32);
   SET hexStr = HEX(b);
   RETURN LOWER(CONCAT(
        SUBSTR(hexStr, 1, 8), '-',
        SUBSTR(hexStr, 9, 4), '-',
        SUBSTR(hexStr, 13, 4), '-',
        SUBSTR(hexStr, 17, 4), '-',
        SUBSTR(hexStr, 21)
    ));
END$$

CREATE FUNCTION UUID_TO_BIN(uuid CHAR(36))
RETURNS BINARY(16)
BEGIN
    RETURN UNHEX(REPLACE(uuid, '-', ''));
END$$

DELIMITER ;

答案 5 :(得分:-1)

在 MySQL 4.0 及更高版本中,您可以像使用 MID 一样更改 UUID 的大小

SELECT MID(UUID(),1,32); # 32 characters long UUID
SELECT MID(UUID(),1,11); # 11 characters long UUID

正如@nickdnk 指出的那样,您不应该这样做。 UUID 的总长度使它们独一无二。将其中的一部分条带化可能会导致非唯一值。