Je programme un script en utilisant PHP et MySQL et je veux obtenir un identifiant unique (composé d'une chaîne: majuscules et minuscules avec des chiffres) comme: gHYtUUi5b
. J'ai trouvé de nombreuses fonctions dans PHP qui peuvent générer de tels nombres mais j'ai peur de savoir comment s'assurer que l'identifiant est unique!
UPDATE : uuid is long, I mean such id like: (P5Dc) an 11 alphanumeric char.
Un manière programmatique peut être:
Remarque:
J'utilise UUID () pour créer une valeur unique.
exemple:
insert into Companies (CompanyID, CompanyName) Values(UUID(), "TestUUID");
Vous aimerez peut-être la façon dont nous procédons. Je voulais un code unique réversible qui semblait "aléatoire" - un problème assez courant.
Nous avons maintenant un numéro qui varie énormément entre les appels et qui est garanti inférieur à 10 000 000 000. Pas un mauvais début.
La raison du choix de la base 34 est pour que nous ne nous inquiétions pas des collisions 0/O et 1/l. Vous disposez maintenant d'une courte clé à recherche aléatoire que vous pouvez utiliser pour rechercher un identifiant de base de données LONG.
Comment vous générez les uniques_id est une question utile - mais vous semblez faire une hypothèse contre-productive sur quand vous les générez!
Mon point est que vous n'avez pas besoin de générer ces identifiants uniques au moment de créer vos lignes, car ils sont essentiellement indépendants des données insérées.
Ce que je fais est de pré-générer des identifiants uniques pour une utilisation future, de cette façon je peux prendre mon propre temps et garantir absolument qu'ils sont uniques, et il n'y a aucun traitement à faire au moment de l'insertion.
Par exemple, j'ai une table de commandes avec order_id dedans. Cet identifiant est généré à la volée lorsque l'utilisateur saisit la commande, de manière incrémentielle 1,2,3, etc. pour toujours. L'utilisateur n'a pas besoin de voir cet identifiant interne.
Ensuite, j'ai une autre table - unique_ids avec (order_id, unique_id). J'ai une routine qui s'exécute chaque nuit et précharge cette table avec suffisamment de lignes unique_id pour couvrir plus que les commandes qui pourraient être insérées dans les prochaines 24 heures. (Si jamais je reçois 10000 commandes en une journée, j'aurai un problème - mais ce serait un bon problème!)
Cette approche garantit l'unicité et élimine toute charge de traitement de la transaction d'insertion et dans la routine de traitement par lots, où elle n'affecte pas l'utilisateur.
Si vous utilisez MySQL avec une version supérieure à 5.7.4, vous pouvez utiliser la fonction RANDOM_BYTES nouvellement ajoutée:
SELECT TO_BASE64(RANDOM_BYTES(16));
Cela se traduira par une chaîne aléatoire telle que GgwEvafNLWQ3+ockEST00A==
.
Utilisez fonction UUID .
Je ne connais pas la source de vos procédures dans PHP qui génère des valeurs uniques. S'il s'agit d'une fonction de bibliothèque, elles devraient garantir que votre valeur est vraiment unique. Consultez la documentation. Vous devriez, en revanche, utilisez cette fonction tout le temps. Si vous, par exemple, utilisez PHP pour générer une valeur unique, puis que vous décidez d'utiliser la fonction MySQL, vous pouvez générer une valeur qui existe déjà. Dans ce cas mettre UNIQUE INDEX sur la colonne est également une bonne idée.
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 "";
DECLARE newUniqueValue 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 ;
Et appelez la procédure stockée en tant que GenerateUniqueValue ('tableName', 'columnName'). Cela vous donnera à chaque fois un caractère unique à 8 chiffres.
Pour unicité, ce que je fais est de prendre l'horodatage Unix et d'y ajouter une chaîne aléatoire et de l'utiliser.
crypt()
comme suggéré et stockez le sel dans un fichier de configuration, démarrez le sel à partir de 1 et si vous trouvez un doublon, passez à la valeur suivante 2. Vous pouvez utiliser 2 caractères, mais cela vous donnera suffisamment de combinaison pour le sel.
Vous pouvez générer une chaîne à partir de openssl_random_pseudo_bytes(8)
. Cela devrait donc donner une chaîne aléatoire et courte (11 caractères) lorsqu'elle est exécutée avec crypt()
.
Supprimez le sel du résultat et il n'y aura que 11 caractères qui devraient être assez aléatoires pour plus de 100 millions si vous changez de sel à chaque échec aléatoire.
<?php
$hostname_conn = "localhost";
$database_conn = "user_id";
$username_conn = "root";
$password_conn = "";
$conn = mysql_pconnect($hostname_conn, $username_conn, $password_conn) or trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db($database_conn,$conn);
// run an endless loop
while(1) {
$randomNumber = Rand(1, 999999);// generate unique random number
$query = "SELECT * FROM tbl_Rand WHERE the_number='".mysql_real_escape_string ($randomNumber)."'"; // check if it exists in database
$res =mysql_query($query,$conn);
$rowCount = mysql_num_rows($res);
// if not found in the db (it is unique), then insert the unique number into data_base and break out of the loop
if($rowCount < 1) {
$con = mysql_connect ("localhost","root");
mysql_select_db("user_id", $con);
$sql = "insert into tbl_Rand(the_number) values('".$randomNumber."')";
mysql_query ($sql,$con);
mysql_close ($con);
break;
}
}
echo "inserted unique number into Data_base. use it as ID";
?>
Ci-dessous est juste pour la référence de l'identifiant aléatoire unique numérique ...
cela peut vous aider ...
$query=mysql_query("select * from collectors_repair");
$row=mysql_num_rows($query);
$ind=0;
if($row>0)
{
while($rowids=mysql_fetch_array($query))
{
$already_exists[$ind]=$rowids['collector_repair_reportid'];
}
}
else
{
$already_exists[0]="nothing";
}
$break='false';
while($break=='false'){
$Rand=mt_Rand(10000,999999);
if(array_search($Rand,$alredy_exists)===false){
$break='stop';
}else{
}
}
echo "random number is : ".$echo;
et vous pouvez ajouter char avec le code comme -> $Rand=mt_Rand(10000,999999) .$randomchar; // assume $radomchar contains char;
Pour obtenir des jetons uniques et aléatoires, vous pouvez simplement chiffrer votre clé primaire, à savoir:
SELECT HEX(AES_ENCRYPT(your_pk,'your_password')) AS 'token' FROM your_table;
C'est assez bon plus son réversible pour que vous n'ayez pas à stocker ce jeton dans votre table mais à le générer à la place.
Un autre avantage est qu'une fois que vous avez décodé votre PK à partir de ce jeton, vous n'avez pas à effectuer de lourdes recherches en texte intégral sur votre table, mais une recherche PK simple et rapide.
Il y a cependant un petit problème. MySql prend en charge différents modes de cryptage de bloc qui, s'ils sont modifiés, changeront complètement votre espace de jetons, rendant les anciens jetons inutiles ...
Pour surmonter cela, vous pouvez définir cette variable avant la génération du jeton, c'est-à-dire:
SET block_encryption_mode = 'aes-256-cbc';
Cependant cela gaspille un peu ... La solution pour cela est d'attacher un marqueur de mode de cryptage utilisé au token:
SELECT CONCAT(CONV(CRC32(@@GLOBAL.block_encryption_mode),10,35),'Z',HEX(AES_ENCRYPT(your_pk,'your_password'))) AS 'token' FROM your_table;
Un autre problème peut survenir si vous souhaitez conserver ce jeton dans votre table sur INSERT
car pour le générer, vous devez connaître la clé primaire de l'enregistrement qui n'a pas encore été inséré ... Bien sûr, vous pourriez simplement INSERT
puis UPDATE
avec LAST_INSERT_ID()
mais encore une fois - il y a une meilleure solution:
INSERT INTO your_table ( token )
SELECT CONCAT(CONV(CRC32(@@GLOBAL.block_encryption_mode),10,35),'Z',HEX(AES_ENCRYPT(your_pk,'your_password'))) AS 'token'
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = "your_table";
Un dernier mais non le moindre avantage de cette solution est que vous pouvez facilement la répliquer en php, python, js ou tout autre langage que vous pourriez utiliser.
Vous pouvez également envisager d'utiliser crypt()
* pour générer un ID unique [presque garanti] dans vos contraintes.
Cela génère des identifiants aléatoires:
CREATE TABLE Persons (
ID Integer PRIMARY KEY AUTOINCREMENT,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Age int
);