web-dev-qa-db-fra.com

PHP/MySQL - Le meilleur moyen de créer une chaîne aléatoire unique?

Comment créer une chaîne unique aléatoire dans MySQL?

quand j'ai besoin de créer une chaîne aléatoire dans PHP, j'utilise cette fonction:

public function generateString($length)
{   
    $charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    for($i=0; $i<$length; $i++) 
        $key .= $charset[(mt_Rand(0,(strlen($charset)-1)))]; 

    return $key;
}

Ensuite, je prenais la chaîne générée et la stockais dans une base de données MySQL. 

Quel est le meilleur moyen de s'assurer que la chaîne aléatoire générée est unique pour toutes les autres chaînes aléatoires créées pour d'autres entrées de la base de données? 

Peut-être quelque chose comme ça?

while(++$i < 100)
{
  //query db with random key to see if there is a match

  //if no match found break out of loop
  break;

}

Cela semble compliqué et long, et je pourrais potentiellement toucher la base de données plusieurs fois. Comment puis-je être rapidement sûr que ma nouvelle chaîne aléatoire est unique?

24
John

En supposant que 10 caractères du jeu de caractères a-z, A-Z, 0-9 signifie qu'il y en a (26 + 26 + 10)dix = 8.39299366 × 1017 combinaisons possibles. Pour calculer les chances d'une collision ... juste 1/x le nombre susmentionné. Je ne voudrais donc pas m'inquiéter d'avoir la même chaîne deux fois. Même si la chaîne est à nouveau identique, je vais simplement réexécuter la fonction dans une boucle, la seule condition de sortie étant qu'une chaîne unique soit trouvée.

7
Salman A

Pourquoi ne pas simplement utiliser les fonctions intégrées pour générer des identifiants uniques? Vous n'auriez pas à vous soucier des doublons de cette façon.

PHP et MySQL ont le leur.

PHP: uniqid()

MySQL: UUID()

17
Mark Biek

SET Rand_str = SUBSTRING(MD5(NOW()),1,$LENGTH); - où LENGTH est compris entre 1 et 32 ​​selon MD5

Quelques exemples sont ci-dessous:

SET Rand_str = SUBSTRING(MD5(NOW()),1,5); - chaîne de 5 caractères

SET Rand_str = SUBSTRING(MD5(NOW()),1,15); - chaîne de 15 caractères

3
rudyrockstar
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 appelez cette procédure stockée en tant que 

Call GenerateUniqueValue('tableName','columnName')

Des chaînes aléatoires uniques peuvent être utilisées comme clés de caractère ou jetons pour identifier les enregistrements de base de données et effectuer un contrôle dans une table de base de données. Cette clé fournit une clé unique avec la variable store $ refer_by.

define('DB_SERVER', "localhost");
define('DB_USER', "root");
define('DB_PASS', "");
define('DB_DATABASE', "student");
$con = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_DATABASE);

function refercode()
{
    $string = '';
    $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    $max = strlen($characters) - 1;
    for ($i = 0; $i < 6; $i++) {
        $string .= $characters[mt_Rand(0, $max)];
    }
    $refer = "select * from user_detail where refer_code = '".$string."' ";
    $coderefertest = mysqli_query($con,$refer);

    if(mysqli_num_rows($coderefertest)>0)
    {
        return refercode();
    }
    else
    {
        return $string;
    }
}
$refer_by = refercode();
0
HARDIK

Je voudrais rendre la colonne de cet identifiant unique dans votre base de données. Ensuite, vous pouvez faire quelque chose comme ceci pour vous protéger contre les collisions:

    $row_count = 0;
    while ($row_count == 0) {
        error_reporting(0);
        $id_string = substr(uniqid(), 0, 10);

        $sql = "UPDATE <table> SET unique_id = :unique_id WHERE <something true>";
        $query = $this->db->prepare($sql);
        $query->execute(array(':unique_id' => $unique_id));
        $row_count = $query->rowCount();
    }

Bien sûr, il peut être nécessaire d’essayer la requête plusieurs fois, mais vous savez ainsi que c’est garanti que votre base de données est unique. La ligne error_reporting (0) est présente pour supprimer tout avertissement éventuellement activé. Le uniqid () de PHP n'est pas non plus le plus unique des générateurs, mais vous pouvez facilement l'échanger pour le vôtre ou simplement profiter du potentiel de collisions possibles ici et là.

0
Tim Trampedach

Si vous souhaitez utiliser ces chaînes à des fins de sécurité, vous devez utiliser openssl_random_pseudo_bytes qui vous indiquera si PHP a été en mesure d'utiliser un algorithme puissant pour le générer:

Ouput a besoin d'être nettoyé. Regardez cette question pour plus d'informations.

0
Simon

Regardez la fonction uniqid et l’extension pecl uuid . L'un ou l'autre peut être utilisé comme base pour générer des guides, bien que si vous envisagez d'avoir un cluster, vous voudrez vous assurer que vous avez quelque chose de plus qui assure que deux serveurs ne génèrent pas le même identifiant. Avoir une configuration par serveur qui ajoute un préfixe ou un suffixe à l'id est suffisant pour résoudre ce problème.

0
gview

J'utilise habituellement:

SELECT LEFT(MD5(id), 8)

variantes par besoins:

SELECT LEFT(UUID(), 8)

SELECT LEFT(MD5(Rand()), 8)
0
Luca C.

Heureusement, les bases de données ont déjà la possibilité de créer des identifiants uniques (numériques). Je suggère l'approche que nous avons adoptée, qui consiste à créer une conversion bidirectionnelle entre un identifiant numérique en augmentation lente et un identifiant alphanumérique. Le fait que ce soit bidirectionnel assure que les versions alphanumériques "aléatoires" sont également uniques sans avoir à les tester explicitement. En effet, je ne stocke que la version numérique dans la base de données (puisque vous l’obtenez gratuitement avec une colonne SERIAL) et n’imprime jamais la version alpha.

Cet exemple génère des ID de sept octets, mais l'approche peut être modifiée de manière triviale pour s'adapter à presque toutes les situations.

Voir: Comment générer un identifiant unique dans MySQL?

0
RJStanford