Вставка и выбор UUID как двоичного (16)

Я не понимаю, почему

SELECT UUID();

Возвращает что-то вроде:

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

Но если я вставляю его в двоичное (16) поле (функция UUID()), например, перед триггером BEFORE INSERT и запускает select, он возвращает что-то вроде:

0782ef48-a439-11

Обратите внимание, что эти два UUID - это не одни и те же данные.

Я понимаю двоичный код, и строка UUID не выглядит идентичной, но не должны ли выбранные данные по крайней мере быть такими же длинными? В противном случае, возможно, он может быть как можно более уникальным?

Лучше ли хранить его как char (36)? Мне просто нужно, чтобы он был уникальным для предотвращения дублирования вставок. Он никогда не выбирается или не используется для соединений.

EDIT:

перед срабатыванием триггера:

BEGIN

if NEW.UUID IS NULL THEN

NEW.UUID = UUID();

END IF

END

Ответ 1

Итак, как ответ на комментарии. Правильный способ сохранить UUID из 36 символов в двоичном виде (16) - выполнить вставку следующим образом:

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

UNHEX, потому что UUID уже является шестнадцатеричным значением. Мы обрезаем (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, вы должны взглянуть на функции UUID, как указано в ответе SlyDave. Этот ответ по-прежнему правильный, но он не оптимизирует индексы UUID, которые могут быть сделаны с помощью этих функций.

Ответ 2

Начиная с MySQL 8, вы можете использовать две новые функции UUID:

  • 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, иначе он не будет преобразован обратно должным образом.

Смотрите документацию для получения более подробной информации.

Ответ 3

Другие ответы верны. Функция 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

Но используйте это в случае, если я сгенерирую свои собственные UUID;

INSERT INTO sometable (id) VALUES 0x3f06af63a93c11e4979700505690773f;

Аналогично, вы можете использовать шестнадцатеричные литералы в своих предложениях WHERE:

SELECT * FROM sometable WHERE id = 0x3f06af63a93c11e4979700505690773f;

Это будет быстрее, если вам не нужно каждый раз преобразовывать данные в строку UUID.

Примечание: 'x' в '0xaBc чувствителен к регистру. Шестнадцатеричные цифры не являются, однако.

Ответ 4

Я использую MariaDB, поэтому семейство функций BIN_TO_UUID не существует. Мне все равно удалось получить соответствующие значения.

bin -> hex

Здесь uuid - это двоичное (16) значение 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)
))

hex -> bin

Здесь cc6e6d97-5501-11e7-b2cb-ceedca613421 - читаемая версия UUID, и вы будете использовать приведенное ниже значение в предложении WHERE для его поиска.

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

Приветствия

Ответ 5

Polyfill для BIN_TO_UUID и UUID_TO_BIN для MySQL 5:

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 ;