Générer un GUID dans MySQL pour les données existantes?

101

Je viens d'importer un tas de données dans une table MySQL et j'ai une colonne "GUID" que je veux essentiellement remplir toutes les lignes existantes avec de nouveaux GUID aléatoires uniques.

Comment faire cela dans MySQL?

j'ai essayé

UPDATE db.tablename
  SET columnID = UUID()
  where columnID is not null

Et que chaque champ soit le même

À M
la source
2
êtes-vous vraiment sûr, ils sont les mêmes? J'ai essayé, la plupart des caractères sont les mêmes, mais il y a quelques différences dans l'uuid généré
xiaoyifang
Oui, je confirme, c'est pareil!
Cyril N.
Cela fonctionne pour moi - les différences sont mineures, mais sont là. Le moyen le plus rapide de vérifier est d'ajouter une contrainte UNIQUE à la colonne.
PSU

Réponses:

88

Je ne sais pas si c'est le moyen le plus simple, mais cela fonctionne. L'idée est de créer un déclencheur qui fait tout son travail pour vous, puis d'exécuter une requête qui met à jour votre table, et enfin de supprimer ce déclencheur:

delimiter //
create trigger beforeYourTableUpdate  BEFORE UPDATE on YourTable
FOR EACH ROW
BEGIN
  SET new.guid_column := (SELECT UUID());
END
//

Puis exécutez

UPDATE YourTable set guid_column = (SELECT UUID());

Et DROP TRIGGER beforeYourTableUpdate;

UPDATE Une autre solution qui n'utilise pas de déclencheurs, mais nécessite une clé primaire ou un index unique:

UPDATE YourTable,
INNER JOIN (SELECT unique_col, UUID() as new_id FROM YourTable) new_data 
ON (new_data.unique_col = YourTable.unique_col)
SET guid_column = new_data.new_id

MISE À JOUR une fois de plus: Il semble que votre requête d'origine devrait également fonctionner (peut-être que vous n'en avez pas besoin WHERE columnID is not null, donc tout mon code sophistiqué n'est pas nécessaire.

a1ex07
la source
ouais, cela devrait fonctionner même en 5.0. Mais n'oubliez pas de laisser tomber la gâchette!
a1ex07
oui bien sûr :) je me demande si je dois vérifier les doublons après ou si cela va créer des valeurs uniques pour chaque ligne de la colonne?
Tom
Si UUIDest mis en œuvre correctement (et je pense que c'est le cas), vous devriez être en mesure de créer un index unique sans vérifier les doublons.
a1ex07
J'ai mis à jour ma réponse avec une autre approche qui peut également être utile.
a1ex07
2
votre code d'origine fonctionnerait, changez simplement columnId = UUID () en columnId = (SELECT UUID ()). A très bien fonctionné pour moi. toutes les valeurs générées sont très proches d'être identiques mais chacune est unique.
EJay
113

J'avais besoin d'ajouter une colonne de clé primaire guid dans une table existante et de la remplir avec des GUID uniques et cette requête de mise à jour avec sélection interne a fonctionné pour moi:

UPDATE sri_issued_quiz SET quiz_id=(SELECT uuid());

Si simple :-)

Rakesh Prajapati
la source
35
Au début, je pensais que cela avait inséré des UUID en double car ils commencent et se terminent tous de la même manière, mais ils sont en fait légèrement différents.
Sam Barnum
3
@SamBarnum car UUIDest généré en fonction de la machine et de l'horodatage . En tant que requête qui prend des millisecondes pour s'exécuter, elles doivent être très très proches en effet ... mais jamais les mêmes ... une bonne chose à vous assurer, c'est d'ajouter un UNIQUEindex à cette colonne.
balexandre
2
La réponse acceptée semble exagérée par rapport à cela!
Xtreme Biker
4
Au moins dans mariadb (10.1.26) cela ne semble pas fonctionner, donnant le même uuid pour chaque enregistrement.
johanvdw
4
Cela a généré le même UUID sur chaque enregistrement pour moi, probablement parce que c'est dans une sous-requête et que MySQL exécutera d'abord la requête interne et utilisera la même valeur pour toutes les lignes. Pour le résoudre, supprimez la sous-requête:UPDATE sri_issued_quiz SET quiz_id=uuid();
Chris White
22

La solution approuvée crée des identifiants uniques, mais à première vue, ils semblent identiques, seuls les premiers caractères diffèrent.

Si vous voulez des clés visiblement différentes, essayez ceci:

update CityPopCountry set id = (select md5(UUID()));


MySQL [imran@lenovo] {world}> select city, id from CityPopCountry limit 10;
+------------------------+----------------------------------+
| city                   | id                               |
+------------------------+----------------------------------+
| A Coruña (La Coruña)   | c9f294a986a1a14f0fe68467769feec7 |
| Aachen                 | d6172223a472bdc5f25871427ba64e46 |
| Aalborg                | 8d11bc300f203eb9cb7da7cb9204aa8f |
| Aba                    | 98aeeec8aa81a4064113764864114a99 |
| Abadan                 | 7aafe6bfe44b338f99021cbd24096302 |
| Abaetetuba             | 9dd331c21b983c3a68d00ef6e5852bb5 |
| Abakan                 | e2206290ce91574bc26d0443ef50fc05 |
| Abbotsford             | 50ca17be25d1d5c2ac6760e179b7fd15 |
| Abeokuta               | ab026fa6238e2ab7ee0d76a1351f116f |
| Aberdeen               | d85eef763393862e5fe318ca652eb16d |
+------------------------+----------------------------------+

J'utilise la version MySQL Server: 5.5.40-0 + wheezy1 (Debian)

Imran-UK
la source
6
Dans mon cas, j'avais besoin de traits d'union dans le GUID généré. J'ai utilisé ceci: la SELECT INSERT(INSERT(INSERT(INSERT(MD5(UUID()), 9, 0, '-'), 14, 0, '-'), 19, 0, '-'), 24, 0, '-')requête n'est pas très jolie mais elle fait le travail.
solo du
9
Le md5 n'est-il pas moins unique que les UUID? Je m'inquiéterais des collisions.
Adam
15
select @i:=uuid();
update some_table set guid = (@i:=uuid());
Brad Johnson
la source
1
parfait parfait parfait !! une si petite chose peut avoir un impact énorme !!
thekosmix
5

Juste un ajout mineur à faire car je me suis retrouvé avec un résultat étrange en essayant de modifier les UUID au fur et à mesure qu'ils étaient générés. J'ai trouvé la réponse par Rakesh était la plus simple qui fonctionnait bien, sauf dans les cas où vous souhaitez supprimer les tirets.

Pour référence:

UPDATE some_table SET some_field=(SELECT uuid());

Cela fonctionnait parfaitement tout seul. Mais quand j'ai essayé ceci:

UPDATE some_table SET some_field=(REPLACE((SELECT uuid()), '-', ''));

Ensuite, toutes les valeurs résultantes étaient les mêmes (pas subtilement différentes - j'ai quadruple vérifié avec une GROUP BY some_fieldrequête). Peu importe comment j'ai placé les parenthèses, la même chose se produit.

UPDATE some_table SET some_field=(REPLACE(SELECT uuid(), '-', ''));

Il semble qu'en entourant la sous-requête pour générer un UUID avec REPLACE, il n'exécute la requête UUID qu'une seule fois, ce qui est probablement parfaitement logique en tant qu'optimisation pour des développeurs beaucoup plus intelligents que moi, mais ce n'est pas le cas pour moi.

Pour résoudre ce problème, je viens de le diviser en deux requêtes:

UPDATE some_table SET some_field=(SELECT uuid());
UPDATE some_table SET some_field=REPLACE(some_field, '-', '');

Solution simple, évidemment, mais j'espère que cela fera gagner à quelqu'un le temps que je viens de perdre.

enobrev
la source
4

On dirait une simple faute de frappe. Vous ne vouliez pas dire "... où columnId est nul"?

UPDATE db.tablename
  SET columnID = UUID()
  where columnID is null
evan.leonard
la source
1
J'ai eu la même pensée quand j'ai lu la question, mais je ne pense pas: on dirait que ses colonnes contiennent des valeurs, mais pas des valeurs UNIQUES. Les réponses données bien avant votre réponse montrent déjà ce qui est nécessaire. Il ne devrait pas y avoir de WHEREclause. Et les valeurs générées sont très similaires, il faut donc les regarder de près pour voir qu'elles sont effectivement différentes.
ToolmakerSteve
3

J'ai été confronté au même problème. Im mon cas uuid est stocké comme BINARY (16) et a des contraintes NOT NULL UNIQUE. Et j'ai été confronté au problème lorsque le même UUID était généré pour chaque ligne, et la contrainte UNIQUE ne le permet pas. Donc, cette requête ne fonctionne pas:

UNHEX(REPLACE(uuid(), '-', ''))

Mais pour moi, cela a fonctionné, lorsque j'ai utilisé une telle requête avec une sélection interne imbriquée:

UNHEX(REPLACE((SELECT uuid()), '-', ''))

Puis est produit un résultat unique pour chaque entrée.

Oleksandr Korniienko
la source
1
UPDATE db.tablename SET columnID = (SELECT UUID()) where columnID is not null
Ashutosh Niranjan
la source
2
Veuillez ajouter quelques explications sur le fonctionnement de votre code. Le code sans commentaires n'est pas toujours facile à comprendre pour les autres utilisateurs de SO
Simas Joneliunas
si vous voulez mettre à jour uuid dans les données existantes, exécutez la requête comme ci-dessus avec votre condition.
Ashutosh Niranjan le
0

MYsql UPDATE nomtable SET columnName = UUID ()

oracle UPDATE nomtable SET columnName = SYS_GUID ();

SQLSERVER UPDATE nomtable SET columnName = NEWID () ;;

Hugo R
la source
0
// UID Format: 30B9BE365FF011EA8F4C125FC56F0F50
UPDATE `events` SET `evt_uid` = (SELECT UPPER(REPLACE(@i:=UUID(),'-','')));

// UID Format: c915ec5a-5ff0-11ea-8f4c-125fc56f0f50
UPDATE `events` SET `evt_uid` = (SELECT UUID());

// UID Format: C915EC5a-5FF0-11EA-8F4C-125FC56F0F50
UPDATE `events` SET `evt_uid` = (SELECT UPPER(@i:=UUID()));
Léonard Filipe
la source