PHP/MySQL - Best way to create unique random string?

How do I create a random unique string in MySQL?

when I need to create a random string in PHP I use this function:

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

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

    return $key;
}

Then I would take the generated string and store it in a MySQL database.

What is the best way to make sure the generated random string is unique to all the other random strings created for other entries in the database?

Maybe something like this?

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

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

}

This seems messy and long, and I could potentially hit the database multiple times. How can I quickly be sure my new random string is unique?

Asked By: John
||

Answer #1:

Assuming 10 characters from the character set a-z, A-Z, 0-9 mean there are (26 + 26 + 10)10 = 8.39299366 × 1017 possible combinations. To calculate the odds of a collision... just 1/x the afore-mentioned number. So I would not be worrying about getting the same string twice. Even if do get the same string again I'll just run the function again in a loop, the only exit condition being that a unique string is found.

Answered By: Salman A

Answer #2:

Why not just use the built-in functions for generating unique identifiers? You wouldn't have to worry about duplicates that way.

Both PHP and MySQL have their own.

PHP: uniqid()

MySQL: UUID()

Answered By: Mark Biek

Answer #3:

SET rand_str = SUBSTRING(MD5(NOW()),1,$LENGTH); -- Where LENGTH is 1 to 32 as per MD5

Some examples are below:

SET rand_str = SUBSTRING(MD5(NOW()),1,5); -- 5 character string

SET rand_str = SUBSTRING(MD5(NOW()),1,15); -- 15 character string

Answered By: rudyrockstar

Answer #4:

I would make the column of this id unique in your DB. Then you can do something like this to safeguard against 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();
    }

Sure, it may need to try the query more than once, but this way you know it's guaranteed to be unique in your DB. The error_reporting(0) line is in there to suppress any warnings which might be turned on. PHP's uniqid() also isn't the most unique generate there is, but you can easily swap that out for your own or just take the hit of potential collisions here and there.

Answered By: Tim Trampedach

Answer #5:

Take a look at the uniqid function and the pecl uuid extension. Either one can be used as the basis for generating guids, although if you plan to have a cluster, you will want to insure that you have something extra that insures that two servers don't generate the same id. Having a per server configuration that adds as prefix or suffix to the id is sufficient to address that issue.

Answered By: gview

Answer #6:

Luckily databases already have the ability to create unique IDs (numeric) - I suggest the approach that we took, which is to create a two-way conversion between a gently increasing numeric ID and an alpha-numeric ID. Having it be two-way assures that the alpha-numeric "random" versions are also unique without having to explicitly test them. Indeed, I only ever store the numeric version in the database (since you get it for free with a SERIAL column) and only ever print the alpha version.

This example generates seven-byte IDs but the approach can be trivially tweaked to fit almost any set of circumstances.

See: How to generate unique id in MySQL?

Answered By: RJStanford

Answer #7:

I usually use:

SELECT LEFT(MD5(id), 8)

variants by needings:

SELECT LEFT(UUID(), 8)

SELECT LEFT(MD5(RAND()), 8)
Answered By: Luca C.

Answer #8:

If you want to use these strings for security purpose, you should use openssl_random_pseudo_bytes which will indicate you if PHP was able to use a strong algorithm to generate it:

Ouput needs some cleaning though. Have a look at this question for more info.

Answered By: Simon

Answer #9:

Unique random strings can be used as character keys or tokens to identify database records and check to database table and provides Unique key with store $refer_by variable.

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();
Answered By: HARDIK

Answer #10:

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 ;

Use this stored procedure and call this stored procedure as

Call GenerateUniqueValue('tableName','columnName')
The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .



# More Articles