Что такое UUID без дефисов
Канонический UUID состоит из 36 символов, потому что 32 шестнадцатеричные цифры разделены четырьмя дефисами на фиксированных позициях. Эти дефисы — пунктуация, а не данные: они нужны, чтобы человек сразу видел структуру 8-4-4-4-12. Уберите их — и никакая информация не потеряется.
Две причины так делать. Первая — хранение: колонка CHAR(36) занимает 36 байт там, где значению нужно 16, поэтому базы предлагают бинарный формат с функцией-помощником вроде UUID_TO_BIN(), а 32-символьная шестнадцатеричная колонка — следующий по смыслу вариант. Вторая — контексты, где дефис мешает: CSS-селекторы и id элементов, имена файлов, некоторые форматы логов.
Ловушка — не дефисы, а регистр и контекст. Шестнадцатеричные цифры сравниваются без учёта регистра, но если в разных частях системы одни и те же id пишутся то с большой, то с маленькой буквы, появятся две строки, которые не пройдут наивную проверку равенства. А UUID_TO_BIN(uuid, 1) в MySQL вообще не просто убирает дефисы: флаг переставляет байты времени, чтобы бинарное значение сортировалось по времени. Это уже настоящее преобразование, а не косметика.
Как использовать
- Сгенерируйте столько UUID, сколько нужно, выше — по умолчанию они строчные и с дефисами.
- Нужен вид из 32 символов? Форматтер UUID конвертирует весь список за раз.
- Конвертируете в коде? Используйте
replace(/-/g, '')в JavaScript илиuuid.hexв Python, а не ручную нарезку строки. - Храните в базе? Предпочтите родной бинарный тип и его функции; 32 символа — это компромисс, а не цель.
Сценарии
- CSS-селекторы и id элементов, где ведущая цифра или дефис в середине ломают селектор.
- Имена файлов и логи, которые должны выживать в shell и в утилитах, считающих дефис началом флага.
- Компактное хранение, где бинарный тип недоступен.
Сравнение UUID без дефисов с другими форматами
| Вариант | Когда использовать |
|---|---|
Канонический (RFC) | 36 символов, строчные, дефисы 8-4-4-4-12. |
Без дефисов | 32 символа, то же значение. |
Верхний регистр | Косметика: сравнение без учёта регистра. |
MySQL UUID_TO_BIN(id, 1) | Не косметика — ещё и перестановка байтов времени. |
Base64 / Base64URL | Настоящее перекодирование, а не просто hex. |
Примеры кода
JavaScript
const id = crypto.randomUUID();
// '4c6e0549-82b1-47b0-9479-211a64583258'
id.replace(/-/g, ''); // '4c6e054982b147b09479211a64583258'
id.replace(/-/g, '').toUpperCase();
// обратно в канонический вид
const hex = '4c6e054982b147b09479211a64583258';
hex.replace(/^(\w{8})(\w{4})(\w{4})(\w{4})(\w{12})$/, '$1-$2-$3-$4-$5');
Python
import uuid
u = uuid.uuid4()
u.hex # '4c6e054982b147b09479211a64583258' (32 символа)
str(u) # '4c6e0549-82b1-47b0-9479-211a64583258'
uuid.UUID(u.hex) == u # True
SQL
-- MySQL: 16 байт вместо 36
ALTER TABLE orders ADD COLUMN id_bin BINARY(16);
UPDATE orders SET id_bin = UUID_TO_BIN(id);
-- второй аргумент переставляет байты времени
SELECT BIN_TO_UUID(id_bin, 1) FROM orders;
-- PostgreSQL: тип uuid сохраняет дефисы
SELECT replace(id::text, '-', '') FROM orders;
Частые вопросы
Удаление дефисов меняет UUID?
Нет. Дефисы — разделители для читаемости; сами 128 бит находятся в 32 шестнадцатеричных символах. Обе формы разбираются в одно значение и принимаются всеми основными библиотеками.
32-символьный UUID — это всё ещё корректный UUID?
Как значение — да, идентификатор тот же. Как строка — строгий формат RFC требует дефисов, поэтому формальный парсер без них строку отвергнет. Практические парсеры обычно мягче — но если вы проверяете регуляркой, решите это осознанно.
А что с верхним регистром?
Регистр — косметика: 4c6e и 4C6E равны. Главное — однообразие внутри системы: смешение регистра — это как раз то, из-за чего две строки не проходят проверку равенства.