Générer une chaîne de 8 caractères aléatoire et unique à l'aide de MySQL

111

Je travaille sur un jeu qui implique des véhicules à un moment donné. J'ai une table MySQL nommée «véhicules» contenant les données sur les véhicules, y compris la colonne «plaque» qui stocke les plaques d'immatriculation des véhicules.

Maintenant, voici la partie avec laquelle j'ai des problèmes. Je dois trouver une plaque d'immatriculation inutilisée avant de créer un nouveau véhicule - il devrait s'agir d'une chaîne aléatoire alphanumérique de 8 caractères. La façon dont j'ai réalisé cela a été d'utiliser une boucle while dans Lua, qui est le langage dans lequel je programme, pour générer des chaînes et interroger la base de données pour voir si elle est utilisée. Cependant, à mesure que le nombre de véhicules augmente, je m'attends à ce que cela devienne encore plus inefficace qu'il l'est actuellement. Par conséquent, j'ai décidé d'essayer de résoudre ce problème en utilisant une requête MySQL.

La requête dont j'ai besoin doit simplement générer une chaîne alphanumérique de 8 caractères qui n'est pas déjà dans le tableau. J'ai de nouveau pensé à l'approche de la boucle de génération et de vérification, mais je ne me limite pas à cette question au cas où il y en aurait une plus efficace. J'ai pu générer des chaînes en définissant une chaîne contenant tous les caractères autorisés et en la sous-chaînant de manière aléatoire, et rien de plus.

Toute aide est appréciée.

Funstein
la source
Dans quelle mesure avez-vous besoin que ces derniers soient aléatoires? Si quelqu'un reçoit une plaque d'immatriculation particulière, est-il important ou non de savoir s'il peut déterminer la plaque d'immatriculation suivante ou précédente que vous avez distribuée?
Damien_The_Unbeliever
@YaK Voir ma réponse sur la façon d'éviter même la petite possibilité de collision
Eugen Rieck

Réponses:

87

Ce problème se compose de deux sous-problèmes très différents:

  • la chaîne doit être apparemment aléatoire
  • la chaîne doit être unique

Bien que le caractère aléatoire soit assez facile à atteindre, l'unicité sans boucle de relance ne l'est pas. Cela nous amène à nous concentrer d'abord sur l'unicité. L'unicité non aléatoire peut être obtenue de manière triviale avecAUTO_INCREMENT . Donc, utiliser une transformation pseudo-aléatoire préservant l'unicité serait bien:

  • Hash a été suggéré par @paul
  • AES-encrypt convient également
  • Mais il y en a une belle: RAND(N)elle - même!

Une séquence de nombres aléatoires créée par la même graine est garantie d'être

  • reproductible
  • différent pour les 8 premières itérations
  • si la graine est un INT32

Nous utilisons donc @ AndreyVolk ou de @ l'approche de GordonLinoff, mais avec une tête de série RAND :

Par exemple, Assumin idest une AUTO_INCREMENTcolonne:

INSERT INTO vehicles VALUES (blah); -- leaving out the number plate
SELECT @lid:=LAST_INSERT_ID();
UPDATE vehicles SET numberplate=concat(
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@lid)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed)*36+1, 1)
)
WHERE id=@lid;
Eugen Rieck
la source
Approche très intéressante, mais vous vouliez probablement dire RAND(LAST_INSERT_ID()); UPDATE vehicles (...) , rand()*36+1, (...)(sinon elle renvoie 8 fois le même caractère). Comment pouvons-nous être sûrs que 8 appels successifs à rand()sont garantis de retourner une séquence différente s'ils sont initialisés avec une graine différente?
RandomSeed
8
Je me demandais juste. Pourquoi utilisez-vous ces nombres ..4294967296)) * 36 + 1?
Mick
7
C'est un peu vieux, mais j'aimerais noter que j'ai dû ajouter FLOOR()autour des paramètres de la deuxième sous-chaîne: à substring('ABC … 789', floor(rand(@seed:= … )*36+1), 1), certaines occasions, la sous-chaîne essayait de choisir le caractère 36.9, qui, arrondi à 37, n'entraînerait aucun caractère choisi.
Phillip Dodson
4
Vous ne pouvez pas appeler une chaîne aléatoire si elle est reproductible. Et les doublons sont également possibles, car vous utilisez floor(). Ce sqlfiddle montre que des doublons sont créés pour des chaînes de trois caractères.
Paul Spiegel
6
@EugenRieck Je ne comprends pas comment vous obtenez vos chiffres ("2 ^ 32 premières itérations"). Mais je n'ai besoin que d'un exemple de doublons pour réfuter ce concept. Pour les identifiants 193844et 775771votre algorithme générera la même chaîne T82X711( démo ).
Paul Spiegel
114

Comme je l'ai dit dans mon commentaire, je ne me soucierais pas de la probabilité de collision. Générez simplement une chaîne aléatoire et vérifiez si elle existe. Si c'est le cas, réessayez et vous ne devriez pas avoir besoin de le faire plus de deux fois à moins que vous n'ayez déjà attribué un grand nombre de plaques.

Une autre solution pour générer une chaîne pseudo-aléatoire de 8 caractères en pure (My) SQL:

SELECT LEFT(UUID(), 8);

Vous pouvez essayer ce qui suit (pseudo-code):

DO 
    SELECT LEFT(UUID(), 8) INTO @plate;
    INSERT INTO plates (@plate);
WHILE there_is_a_unique_constraint_violation
-- @plate is your newly assigned plate number

Étant donné que cet article a reçu un niveau d'attention inattendu, permettez-moi de souligner le commentaire de l'ADTC : le morceau de code ci-dessus est assez stupide et produit des chiffres séquentiels.

Pour un hasard un peu moins stupide, essayez plutôt quelque chose comme ceci:

SELECT LEFT(MD5(RAND()), 8)

Et pour un vrai hasard (cryptograpiquement sécurisé), utilisez RANDOM_BYTES()plutôt que RAND()(mais j'envisagerais alors de déplacer cette logique vers la couche application).

RandomSeed
la source
Merci pour votre solution, j'ai une question concernant l'UUID. combien de chances l'id que vous générez 8 caractères est à nouveau répété.
TR-Ahmed
1
@ user3099183 Officiellement , "très faible". 16 ^ 8 représente environ 4 milliards de chaînes possibles.
RandomSeed
23
Veuillez noter que les 8 premiers caractères de l'UUID ne sont pas aléatoires, mais séquentiels, car ils sont basés sur l'horodatage.
ADTC
Je veux générer une chaîne aléatoire longue de 9 caractères, et lorsque j'utilise 9dans votre code SELECT LEFT(UUID(), 9);, il y a toujours -à la fin de la chaîne générée comme neuvième caractère. C'est constant. Pourquoi?
Martin AJ
3
@MartinAJ car la chaîne est un uuid . Vous pouvez facilement remplacer les tirets, par exempleSELECT LEFT(REPLACE(UUID(), '-', ''), 16);
jchook
53

Qu'en est-il du calcul du hachage MD5 (ou autre) d'entiers séquentiels, puis en prenant les 8 premiers caractères.

c'est à dire

MD5(1) = c4ca4238a0b923820dcc509a6f75849b => c4ca4238
MD5(2) = c81e728d9d4c2f636f067f89cc14862c => c81e728d
MD5(3) = eccbc87e4b5ce2fe28308fd9f2a7baf3 => eccbc87e

etc.

mise en garde: je n'ai aucune idée du nombre que vous pourriez allouer avant une collision (mais ce serait une valeur connue et constante).

edit: C'est maintenant une vieille réponse, mais je l'ai revu avec le temps sur mes mains, donc, de l'observation ...

Chance de tous les nombres = 2,35%

Chance de toutes les lettres = 0,05%

Première collision lorsque MD5 (82945) = "7b763dcb ..." (même résultat que MD5 (25302))

Paul
la source
2
Bonne idée, pourrait l'utiliser sur la clé primaire. Gardera cela à l'esprit pour les projets futurs, merci!
funstein
2
Il y a une chance que cela puisse résulter avec seulement des chiffres
Mladen Janjetovic
9
Ce n'est pas du tout aléatoire.
paul
1
Vous pouvez le rendre plus "aléatoire" si, au lieu d'utiliser l'ID incrémentiel automatique, vous utilisez la date et l'heure dans laquelle l'insertion a été effectuée, qui est également unique.
Javier La Banca
35

Créer une chaîne aléatoire

Voici une fonction MySQL pour créer une chaîne aléatoire d'une longueur donnée.

DELIMITER $$

CREATE DEFINER=`root`@`%` FUNCTION `RandString`(length SMALLINT(3)) RETURNS varchar(100) CHARSET utf8
begin
    SET @returnStr = '';
    SET @allowedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    SET @i = 0;

    WHILE (@i < length) DO
        SET @returnStr = CONCAT(@returnStr, substring(@allowedChars, FLOOR(RAND() * LENGTH(@allowedChars) + 1), 1));
        SET @i = @i + 1;
    END WHILE;

    RETURN @returnStr;
END

Usage SELECT RANDSTRING(8) pour renvoyer une chaîne de 8 caractères.

Vous pouvez personnaliser le @allowedChars .

L'unicité n'est pas garantie - comme vous le verrez dans les commentaires sur d'autres solutions, ce n'est tout simplement pas possible. Au lieu de cela, vous devrez générer une chaîne, vérifier si elle est déjà utilisée et réessayer si elle l'est.


Vérifiez si la chaîne aléatoire est déjà utilisée

Si nous voulons garder le code de vérification de collision hors de l'application, nous pouvons créer un déclencheur:

DELIMITER $$

CREATE TRIGGER Vehicle_beforeInsert
  BEFORE INSERT ON `Vehicle`
  FOR EACH ROW
  BEGIN
    SET @vehicleId = 1;
    WHILE (@vehicleId IS NOT NULL) DO 
      SET NEW.plate = RANDSTRING(8);
      SET @vehicleId = (SELECT id FROM `Vehicle` WHERE `plate` = NEW.plate);
    END WHILE;
  END;$$
DELIMITER ;
Paddy Mann
la source
6
cela devrait être la réponse acceptée, claire et pertinente, a très bien fonctionné pour moi, merci @ paddy-mann
Saif
C'est la meilleure solution que je pense. Merci mec!
Pronoy999
23

Voici une façon d'utiliser les caractères alphanumériques comme caractères valides:

select concat(substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
              substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1)
             ) as LicensePlaceNumber;

Notez qu'il n'y a aucune garantie d'unicité. Vous devrez vérifier cela séparément.

Gordon Linoff
la source
7
utilisez plutôt floor (rand () * 36 + 1). Sinon, certains résultats seront «courts».
Fraggle
2
il devrait y avoir 35 + 1 et non 36 + 1! Sinon, vous obtiendrez des chaînes avec 8 caractères et d'autres avec 7
BIOHAZARD
23

Voici une autre méthode pour générer une chaîne aléatoire:

SELECT SUBSTRING(MD5(RAND()) FROM 1 FOR 8) AS myrandomstring

êtrealex
la source
16

Vous pouvez utiliser les fonctions rand () et char () de MySQL :

select concat( 
    char(round(rand()*25)+97),
    char(round(rand()*25)+97),
    char(round(rand()*25)+97),
    char(round(rand()*25)+97),
    char(round(rand()*25)+97),
    char(round(rand()*25)+97),
    char(round(rand()*25)+97),
    char(round(rand()*25)+97)
) as name;
Andrey Volk
la source
14

Vous pouvez générer une chaîne alphanumérique aléatoire avec:

lpad(conv(floor(rand()*pow(36,8)), 10, 36), 8, 0);

Vous pouvez l'utiliser dans un BEFORE INSERTdéclencheur et rechercher un doublon dans une boucle while:

CREATE TABLE `vehicles` (
    `plate` CHAR(8) NULL DEFAULT NULL,
    `data` VARCHAR(50) NOT NULL,
    UNIQUE INDEX `plate` (`plate`)
);

DELIMITER //
CREATE TRIGGER `vehicles_before_insert` BEFORE INSERT ON `vehicles`
FOR EACH ROW BEGIN

    declare str_len int default 8;
    declare ready int default 0;
    declare rnd_str text;
    while not ready do
        set rnd_str := lpad(conv(floor(rand()*pow(36,str_len)), 10, 36), str_len, 0);
        if not exists (select * from vehicles where plate = rnd_str) then
            set new.plate = rnd_str;
            set ready := 1;
        end if;
    end while;

END//
DELIMITER ;

Maintenant, insérez simplement vos données comme

insert into vehicles(col1, col2) values ('value1', 'value2');

Et le déclencheur générera une valeur pour le plate colonne.

( démo sqlfiddle )

Cela fonctionne de cette façon si la colonne autorise les valeurs NULL. Si vous voulez qu'il ne soit PAS NULL, vous devez définir une valeur par défaut

`plate` CHAR(8) NOT NULL DEFAULT 'default',

Vous pouvez également utiliser n'importe quel autre algorithme de génération de chaîne aléatoire dans le déclencheur si les alphanumériques majuscules ne sont pas ce que vous voulez. Mais le déclencheur prendra soin de l'unicité.

Paul Spiegel
la source
Incroyable! C'est exactement ce que je voulais. Je voudrais seulement comprendre comment il est converti en chaîne. Pourquoi y a-t-il un pow, que faire, pour ajouter des chiffres, etc. Quoi qu'il en soit, merci.
Akxe
@Akxe conv () peut être utilisé pour convertir un nombre en chaîne alphanumérique. pow(36,8)-1est la représentation numérique de ZZZZZZZZ. Nous générons donc un entier aléatoire entre 0et '36 ^ 8-1 '(de 0à 2821109907455) et le convertissons en une chaîne alphanumérique entre 0et ZZZZZZZZunsing conv(). lapad () remplira la chaîne de zéros jusqu'à ce qu'elle ait une longueur de 8.
Paul Spiegel
Vous, monsieur, êtes un génie. J'imagine que l'ajout de petites lettres est impossible en raison de la non-continuité des caractères? (91-96) Pas que j'en ai besoin, juste curieux ...
Akxe
@Akxe conv()ne prend en charge qu'une base jusqu'à 36 (10 chiffres + 26 lettres majuscules). Si vous souhaitez inclure des lettres minuscules, vous aurez besoin d'un autre moyen de convertir un nombre en chaîne.
Paul Spiegel
Attention: ne fonctionne pas pour str_len> 13. A partir de 14, vous obtenez toujours '3W5E11264SGSF'. ;-)
Gerard H. Pille
6

Pour générer une chaîne aléatoire, vous pouvez utiliser:

SUBSTRING(MD5(RAND()) FROM 1 FOR 8)

Vous recevez comme ça:

353E50CC

Nikita G.
la source
5

Pour une chaîne composée de 8 nombres aléatoires et de lettres majuscules et minuscules, voici ma solution:

LPAD(LEFT(REPLACE(REPLACE(REPLACE(TO_BASE64(UNHEX(MD5(RAND()))), "/", ""), "+", ""), "=", ""), 8), 8, 0)

Expliqué de l'intérieur:

  1. RAND génère un nombre aléatoire entre 0 et 1
  2. MD5 calcule la somme MD5 de (1), 32 caractères de af et 0-9
  3. UNHEX traduit (2) en 16 octets avec des valeurs de 00 à FF
  4. TO_BASE64 encode (3) en base64, 22 caractères de az et AZ et 0-9 plus "/" et "+", suivis de deux "="
  5. les trois REPLACEsuppriment les caractères "/", "+" et "=" de (4)
  6. LEFT prend les 8 premiers caractères de (5), remplacez 8 par autre chose si vous avez besoin de plus ou moins de caractères dans votre chaîne aléatoire
  7. LPADinsère des zéros au début de (6) s'il comporte moins de 8 caractères; encore une fois, remplacez 8 par autre chose si nécessaire
Jan Uhlig
la source
Super, exactement ce que je cherchais pour créer un identifiant de type token nativement dans MySQL
rabudde
4

I Utiliser les données d'une autre colonne pour générer un "hachage" ou une chaîne unique

UPDATE table_name SET column_name = Right( MD5(another_column_with_data), 8 )
Richard Fragiacomo
la source
4

8 lettres de l'alphabet - Tout en majuscules:

UPDATE `tablename` SET `tablename`.`randomstring`= concat(CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25)))CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))));
TV-C-15
la source
3

Si vous n'avez pas d'identifiant ou de graine, comme c'est pour une liste de valeurs dans insérer:

REPLACE(RAND(), '.', '')
Ekerner
la source
2

Solution simple et efficace pour obtenir une chaîne aléatoire de 10 caractères avec des lettres et des chiffres majuscules et minuscules:

select substring(base64_encode(md5(rand())) from 1+rand()*4 for 10);
Antarès
la source
1

Si vous êtes d'accord avec des plaques d'immatriculation «aléatoires» mais entièrement prévisibles, vous pouvez utiliser un registre à décalage à rétroaction linéaire pour choisir le numéro de plaque suivant - il est garanti de parcourir chaque numéro avant de le répéter. Cependant, sans quelques mathématiques complexes, vous ne pourrez pas parcourir chaque chaîne alphanumérique de 8 caractères (vous obtiendrez 2 ^ 41 sur les 36 ^ 8 (78%) plaques possibles). Pour que cela remplisse mieux votre espace, vous pouvez exclure une lettre des plaques (peut-être O), ce qui vous donne 97%.

τεκ
la source
1

Compte tenu du nombre total de caractères dont vous avez besoin, vous auriez une très petite chance de générer deux plaques d'immatriculation exactement similaires. Ainsi, vous pourriez probablement vous en sortir avec la génération des nombres dans LUA.

Vous avez 36 ^ 8 plaques d'immatriculation uniques différentes (2,821,109,907,456, c'est beaucoup), même si vous aviez déjà un million de plaques d'immatriculation, vous auriez une très petite chance d'en générer une que vous avez déjà, environ 0,000035%

Bien sûr, tout dépend du nombre de plaques d'immatriculation que vous finirez par créer.

Lawrence Andrews
la source
Certes, je continuerai à le faire dans le jeu réel au lieu de SQL. Merci beaucoup.
funstein
1

Cette fonction génère une chaîne aléatoire en fonction de la longueur de votre entrée et des caractères autorisés comme ceci:

SELECT str_rand(8, '23456789abcdefghijkmnpqrstuvwxyz');

code de fonction:

DROP FUNCTION IF EXISTS str_rand;

DELIMITER //

CREATE FUNCTION str_rand(
    u_count INT UNSIGNED,
    v_chars TEXT
)
RETURNS TEXT
NOT DETERMINISTIC
NO SQL
SQL SECURITY INVOKER
COMMENT ''
BEGIN
    DECLARE v_retval TEXT DEFAULT '';
    DECLARE u_pos    INT UNSIGNED;
    DECLARE u        INT UNSIGNED;

    SET u = LENGTH(v_chars);
    WHILE u_count > 0
    DO
      SET u_pos = 1 + FLOOR(RAND() * u);
      SET v_retval = CONCAT(v_retval, MID(v_chars, u_pos, 1));
      SET u_count = u_count - 1;
    END WHILE;

    RETURN v_retval;
END;
//
DELIMITER ;

Ce code est basé sur la fonction de chaîne aléatoire envoyée par "Ross Smith II"

Mahoor13
la source
Cette fonction ne générera pas de valeur unique aléatoire.
Faisal
1

Pour créer un alphanumérique aléatoire à 10 chiffres , à l'exclusion des caractères sosies 01oOlI:

LPAD(LEFT(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TO_BASE64(UNHEX(MD5(RAND()))), "/", ""), "+", ""), "=", ""), "O", ""), "l", ""), "I", ""), "1", ""), "0", ""), "o", ""), 10), 10, 0)

C'est exactement ce dont j'avais besoin pour créer un code de bon d'achat . Les caractères déroutants sont supprimés pour réduire les erreurs lors de la saisie dans un formulaire de code de bon.

Espère que cela aide quelqu'un, basé sur la réponse brillante de Jan Uhlig .

Veuillez consulter la réponse de Jan pour une description du fonctionnement de ce code.

Paul Harris
la source
0
DELIMITER $$

USE `temp` $$

DROP PROCEDURE IF EXISTS `GenerateUniqueValue`$$

CREATE PROCEDURE `GenerateUniqueValue`(IN tableName VARCHAR(255),IN columnName VARCHAR(255)) 
BEGIN
    DECLARE uniqueValue VARCHAR(8) DEFAULT "";
    WHILE LENGTH(uniqueValue) = 0 DO
        SELECT CONCAT(SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', RAND()*34+1, 1)
                ) INTO @newUniqueValue;
        SET @rcount = -1;
        SET @query=CONCAT('SELECT COUNT(*) INTO @rcount FROM  ',tableName,' WHERE ',columnName,'  like ''',@newUniqueValue,'''');
        PREPARE stmt FROM  @query;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    IF @rcount = 0 THEN
            SET uniqueValue = @newUniqueValue ;
        END IF ;
    END WHILE ;
    SELECT uniqueValue;
    END$$

DELIMITER ;

Utilisez cette procédure stockée et utilisez-la à chaque fois comme

Call GenerateUniqueValue('tableName','columnName')
Hariramprasath Nandhagopalan
la source
0

Un moyen simple de générer un numéro unique

set @i = 0;
update vehicles set plate = CONCAT(@i:=@i+1, ROUND(RAND() * 1000)) 
order by rand();
Gautier
la source
0

Je cherchais quelque chose de similaire et j'ai décidé de créer ma propre version où vous pouvez également spécifier une graine différente si vous le souhaitez (liste de caractères) comme paramètre:

CREATE FUNCTION `random_string`(length SMALLINT(3), seed VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
    NO SQL
BEGIN
    SET @output = '';

    IF seed IS NULL OR seed = '' THEN SET seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; END IF;

    SET @rnd_multiplier = LENGTH(seed);

    WHILE LENGTH(@output) < length DO
        # Select random character and add to output
        SET @output = CONCAT(@output, SUBSTRING(seed, RAND() * (@rnd_multiplier + 1), 1));
    END WHILE;

    RETURN @output;
END

Peut être utilisé comme:

SELECT random_string(10, '')

Ce qui utiliserait la graine intégrée de caractères majuscules et minuscules + chiffres. NULL serait également une valeur au lieu de «».

Mais on pourrait spécifier une graine personnalisée lors de l'appel:

SELECT random_string(10, '1234')
Maarten Ureel
la source