web-dev-qa-db-fra.com

Insertion et sélection des UUID en tant que binaires (16)

Je ne comprends pas pourquoi

SELECT UUID();

Renvoie quelque chose comme:

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

Mais si je l'insère dans un champ binaire (16) (la fonction UUID ()) avec, par exemple, un déclencheur BEFORE INSERT et exécute une sélection, il retourne quelque chose comme:

0782ef48-a439-11

Notez que ces deux UUID ne sont pas les mêmes données.

Je me rends compte que binaire et une chaîne UUID ne semblent pas identiques, mais les données sélectionnées ne devraient-elles pas au moins être aussi longues? Sinon, comment peut-il être tout aussi probable d'être unique?

Est-il préférable de le stocker en tant que caractère (36)? J'ai juste besoin que ce soit unique pour éviter les insertions en double. Il n'est jamais sélectionné ni utilisé pour les jointures.

MODIFIER:

avant le déclenchement serait comme:

BEGIN

if NEW.UUID IS NULL THEN

NEW.UUID = UUID();

END IF

END
13
nickdnk

Donc, en réponse aux commentaires. La bonne façon de stocker un UUID de 36 caractères sous forme binaire (16) consiste à effectuer l'insertion de la manière suivante:

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

UNHEX car un UUID est déjà une valeur hexadécimée. Nous ajustons (REPLACE) les tirets dans l'instruction afin de ramener la longueur à 32 ASCII caractères (nos 16 octets représentés par HEX). Vous pouvez le faire à tout moment avant de le stocker, bien entendu, pour éviter que la base de données ne la gère.

Vous pouvez récupérer l'UUID comme ceci:

SELECT HEX(UUID) FROM sometable;

Juste au cas où quelqu'un tombe sur ce fil et ne sait pas comment cela fonctionne.

Et rappelez-vous: si vous sélectionnez une ligne à l'aide de l'UUID, utilisez UNHEX() à la condition :

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

Et pas HEX()sur la colonne:

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

La deuxième solution, pour que cela fonctionne, requiert que MySQL HEXes tous les UUID avant de pouvoir déterminer quelles lignes correspondent. C'est très inefficace.

Edit: Si vous utilisez MySQL 8, vous devriez jeter un coup d’œil aux fonctions UUID mentionnées dans la réponse de SlyDave. Cette réponse est toujours correcte, mais elle n'optimise pas les index UUID pouvant être créés de manière native à l'aide de ces fonctions.

44
nickdnk

Depuis MySQL 8, vous pouvez utiliser deux nouvelles fonctions 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));
    

Cette méthode prend également en charge la réorganisation du composant temporel de uuid pour améliorer les performances d'indexation (en le classant par ordre chronologique), définissez simplement le deuxième argument sur true - cela ne fonctionne que pour UUID1. 

Si vous utilisez l'indicateur true sur UUID_TO_BIN pour les performances d'indexation (recommandé), vous devez également le définir sur BIN_TO_UUID, sinon la conversion ne sera pas correctement effectuée.

Voir la documentation pour plus de détails. 

14
SlyDave

J'utilise MariaDB alors la famille de fonctions BIN_TO_UUID n'existe pas. J'ai quand même réussi à obtenir les valeurs correspondantes.

bin -> hex

Ici, uuid est la valeur binaire (16) d'un uuid; vous utiliserez la valeur ci-dessous pour SÉLECTIONNER une version lisible de celle-ci.

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

Ici, cc6e6d97-5501-11e7-b2cb-ceedca613421 est une version lisible d'un UUID et vous utiliserez la valeur ci-dessous dans une clause WHERE pour le rechercher.

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

À votre santé

2
Alain Tiemblo

Les autres réponses sont correctes. La fonction UUID() renvoie une chaîne de 36 caractères qui doit être convertie à l'aide des fonctions indiquées (UNHEX() ou, sur les nouvelles plates-formes, UUID_TO_BIN()).

Cependant, si vous utilisez votre propre logiciel pour créer vos UUID, vous pouvez utiliser la notation Hexadecimal Literal .

Je voudrais donc utiliser ce qui suit avec la fonction MySQL UUID():

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

Mais utilisez ceci au cas où je générerais mes propres UUID;

INSERT INTO sometable (id) VALUES 0x3f06af63a93c11e4979700505690773f;

De même, vous pouvez utiliser les littéraux hexadécimaux dans vos clauses WHERE:

SELECT * FROM sometable WHERE id = 0x3f06af63a93c11e4979700505690773f;

Cela sera plus rapide si vous n'avez pas à convertir vos données en chaîne UUID à chaque fois.

Remarque: le 'x' dans '0xaBc est sensible à la casse. Les chiffres hexadécimaux ne le sont pas.

0
Alexis Wilke