web-dev-qa-db-fra.com

Comment générer une chaîne aléatoire unique pour l'une de mes colonnes de table MySql?

J'utilise MySql 5.5.37. J'ai un tableau avec les colonnes suivantes

+------------------+------------------+------+-----+---------+-------+
| Field            | Type             | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+-------+
| ID               | varchar(32)      | NO   | PRI | NULL    |       |
| CODE             | varchar(6)       | NO   | UNI | NULL    |       |

La colonne de code est unique et ma colonne ID est un GUID. J'aimerais mettre à jour un certain nombre de lignes, en fonction de certains critères du tableau ci-dessus (par exemple, WHERE COLUMN1 = 0). Comment générer des codes aléatoires et uniques à 6 caractères (idéalement des lettres et des chiffres) pour ma colonne CODE, de manière à ne pas violer la contrainte unique de mon tableau? Notez que les colonnes de la table qui ne répondent pas aux critères (par exemple, où COLUMN1 <> 0) ont déjà des valeurs uniques pour la colonne CODE.

Modifier: C’est différent de cette question - Génération d’une chaîne aléatoire et unique de 8 caractères avec MySQL car ce lien traite des ID qui sont numériques. Mes identifiants sont des chaînes de 32 caractères. De plus, leur solution ne tient pas compte du fait qu'il peut y avoir des valeurs dans la table avant d'exécuter les instructions que je veux exécuter qui vont générer des valeurs uniques pour la colonne en question.

16
Dave

BEFORE UPDATE solution de déclenchement:

Vous pouvez créer une chaîne alphanumérique alphanumérique aléatoire de 6 caractères avec:

lpad(conv(floor(Rand()*pow(36,6)), 10, 36), 6, 0);

Pour ne pas créer une chaîne existante, vous pouvez utiliser un déclencheur BEFORE UPDATE

DELIMITER //
CREATE TRIGGER `unique_codes_before_update`
BEFORE UPDATE ON `unique_codes` FOR EACH ROW 
BEGIN
    declare ready int default 0;
    declare rnd_str text;
    if new.CODE is null then
        while not ready do
            set rnd_str := lpad(conv(floor(Rand()*pow(36,6)), 10, 36), 6, 0);
            if not exists (select * from unique_codes where CODE = rnd_str) then
                set new.CODE = rnd_str;
                set ready := 1;
            end if;
        end while;
    end if;
END//
DELIMITER ;

Chaque fois que vous définissez votre colonne CODE sur NULL dans une instruction UPDATE, le déclencheur créera une nouvelle chaîne aléatoire dans une boucle jusqu'à ce qu'aucune correspondance ne soit trouvée dans la table.

Vous pouvez maintenant remplacer toutes les valeurs NULL par:

update unique_codes set CODE = NULL where code is NULL;

Dans la démonstration de SQLFiddle, ici i utilise une chaîne aléatoire d’un caractère pour démontrer qu’aucune valeur n’est dupliquée.

Vous pouvez également utiliser le même code dans un déclencheur BEFORE INSERT. De cette façon, vous pouvez simplement insérer de nouvelles lignes avec CODE=NULL et le déclencheur le définira comme nouvelle chaîne aléatoire unique. Et vous n'aurez plus jamais besoin de le mettre à jour.

Réponse originale (chaînes de 32 caractères):

select lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0) as rnd_str_8;

-- output example: 3AHX44TF

générera une chaîne aléatoire alphanumérique de 8 caractères. Concaténer quatre d'entre eux pour obtenir 32 caractères:

select concat(
    lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0),
    lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0),
    lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0),
    lpad(conv(floor(Rand()*pow(36,8)), 10, 36), 8, 0)
) as rnd_str_32;

-- output example: KGC8A8EGKE7E4MGD4M09U9YWXVF6VDDS

http://sqlfiddle.com/#!9/9eecb7d/76933

Alors, qu'en est-il de l'uniqness? Eh bien - essayez de générer des doublons ;-)

16
Paul Spiegel
CONV(CONV(( SELECT MAX(CODE) FROM tbl ), 36, 10) + 1, 10, 36)

vous obtiendrez le prochain «numéro» encodé en base 36 (chiffres et lettres majuscules).

Par exemple:

SELECT CONV(CONV(( 'A1B2C' ), 36, 10) + 1, 10, 36); --> 'A1B2D'
1
Rick James
DELIMITER $$

USE `db` $$

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 ;

Appelez cette procédure stockée comme 

Call GenerateUniqueValue('tableName','columnName')

Cela vous donnera une chaîne unique de 8 caractères à chaque fois. 

Essayez ceci pour le code

SELECT LEFT(MD5(NOW()), 6) AS CODE;

LEFT(MD5(NOW()), 6) ceci retournera un code unique avec 6 caractères.

Essayez d'une autre manière comme ça 

SELECT LEFT(UUID(), 6);

LEFT(UUID(), 6) Ceci retournera également un code unique

0
krunal nerikar