PHP / MySQL - 创建唯一随机字符串的最佳方法?

时间:2011-10-25 17:25:00

标签: php mysql

如何在MySQL中创建随机唯一字符串?

当我需要在PHP中创建随机字符串时,我使用此函数:

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

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

    return $key;
}

然后我将获取生成的字符串并将其存储在MySQL数据库中。

确保生成的随机字符串对于为数据库中的其他条目创建的所有其他随机字符串是唯一的最佳方法是什么?

也许是这样的?

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

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

}

这看起来很乱,很长,我可能会多次打到数据库。如何快速确定我的新随机字符串是否唯一?

10 个答案:

答案 0 :(得分:17)

为什么不使用内置函数生成唯一标识符?你不必担心重复这种方式。

PHP和MySQL都有自己的。

PHP:uniqid()

MySQL:UUID()

答案 1 :(得分:7)

假设字符集a-z, A-Z, 0-9中的10个字符表示存在(26 + 26 + 10) 10 = 8.39299366×10 17 可能的组合。计算碰撞的几率......仅为上述数字的1 / x。所以我不会担心两次获得相同的字符串。即使再次获得相同的字符串,我也只是在循环中再次运行该函数,唯一的退出条件是找到一个唯一的字符串。

答案 2 :(得分:3)

SET rand_str = SUBSTRING(MD5(NOW()),1,$LENGTH); - 根据MD5,LENGTH为1到32

以下是一些例子:

SET rand_str = SUBSTRING(MD5(NOW()),1,5); - 5个字符串

SET rand_str = SUBSTRING(MD5(NOW()),1,15); - 15个字符串

答案 3 :(得分:0)

查看uniqid函数和pecl uuid extension。任何一个都可以用作生成guid的基础,但是如果你计划拥有一个集群,你需要确保你有额外的东西来确保两个服务器不生成相同的id。将每个服务器配置添加为id的前缀或后缀足以解决该问题。

答案 4 :(得分:0)

幸运的是,数据库已经能够创建唯一的ID(数字) - 我建议采用的方法是在轻微增加的数字ID和字母数字ID之间创建双向转换。让它双向确保字母数字“随机”版本也是唯一的,而不必明确地测试它们。实际上,我只将数字版本存储在数据库中(因为您可以通过SERIAL列免费获得它)并且只打印alpha版本。

此示例生成七字节ID,但可以轻松调整方法以适应几乎任何情况。

请参阅:How to generate unique id in MySQL?

答案 5 :(得分:0)

我会在您的数据库中使此ID的列唯一。然后你可以做这样的事情来防止碰撞:

    $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();
    }

当然,它可能需要多次尝试查询,但这样您就知道它在数据库中保证是唯一的。 error_reporting(0)行用于抑制可能打开的任何警告。 PHP的uniqid()也不是最独特的生成,但你可以轻松地将它交换出来,或者只是在这里和那里捕获潜在的碰撞。

答案 6 :(得分:0)

我通常使用:

SELECT LEFT(MD5(id), 8)

需要的变种:

SELECT LEFT(UUID(), 8)

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

答案 7 :(得分:0)

如果您想将这些字符串用于安全目的,您应该使用openssl_random_pseudo_bytes来表明PHP是否能够使用强大的算法来生成它:

输出需要一些清洁。有关详细信息,请查看this question

答案 8 :(得分:0)

唯一的随机字符串可用作字符键或标记来标识数据库记录并检查数据库表,并提供带有存储$ 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();

答案 9 :(得分: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 ;

使用此存储过程并将此存储过程称为

Call GenerateUniqueValue('tableName','columnName')