繁体   English   中英

插入由8个随机字符组成的唯一字符串

[英]Insert unique strings of 8 random characters

我正在使用PHP和MySQL,并且有一个包含3个字段的表格(( IDUsernamePID )。

我希望PID字段包含8个唯一字符的字符串。

我的解决方案是在PHP中生成随机字符串并检查它是否存在。 如果存在,则将生成另一个字符串。

有没有更好的解决方案可以节省处理时间,例如MySQL触发器或类似的东西?

这将为您提供一个随机的8个字符串:

substr(str_pad(dechex(mt_rand()), 8, '0', STR_PAD_LEFT), -8);

在这里找到: http : //www.richardlord.net/blog/php-password-security

或者,如果用户名字段是唯一的,您还可以使用:

substr(md5('username value'), 0, 8);

尽管这是极不可能的,特别是对于md5,但这两种情况都不保证唯一的字符串,因此我可能会执行以下操作:

// Handle user registration or whatever...

function generatePID($sUsername) {
    return substr(md5($sUsername), 0, 8);
}

$bUnique = false;
$iAttempts = 0;

while (!$bUnique && $iAttempts < 10) {
    $aCheck = $oDB->findByPID(generatePID("username value")); // Query the database for a PID matching whats generated
    if (!$aCheck) { // If nothing is found, exit the loop
        $bUnique = true;
    } else {
        $iAttempts++;
    }
}

// Save PID and such...

...这可能只会产生1个“检查”查询,在特殊情况下可能会产生2个查询,并确保一个唯一的字符串。

您可以通过以下方式在Mysql中创建8个字符的唯一字符串

CAST(MD5(RAND()) as CHAR(8))

字符需要随机吗? 还是唯一? 如果它们仅需要唯一,则可以使用时间戳。 基于时间的价值将确保唯一性。

如果您走另一条路线,则必须对照数据库检查您生成的值,直到获得唯一值。

为什么不以正确的方式执行此操作并使用始终唯一的UUID(又称GUID),而无需检查它们是否为唯一。 它可能是36个字符,但是您可以将它们存储为十六进制,这可以节省磁盘空间并比标准CHAR数据提高速度。

您可以阅读PHP文档上有关执行此功能的注释。

我的解决方案是在PHP中生成随机字符串并检查它是否存在。 如果存在,则将生成另一个字符串。

这是错误的方法。 Web服务器将同时运行您的代码的多个实例,迟早两个实例在数据库中存储相同的PID

解决此问题的正确方法是使PID列成为UNIQUE ,而不必进行任何预检查。 只需运行INSERT查询,然后检查结果即可。

如果结果是1062 (ER_DUP_ENTRY)错误,请生成新的PID然后重试。

任何其他数据库错误都应像平常一样处理。

可能是这样的(未经测试):

<?php

/* $link = MySQLi connection */

if (!($stmt = mysqli_prepare ('INSERT `t` (`ID`, `Username`, `PID`) VALUES (?, ?, ?)'))) {
    /* Prepare error */
}
if (!mysqli_bind_param ('iss', $id, $user, $pid) {
    /* Bind error */
}

$e = 0;

for ($i = 0; $i < 10; $i++) {
    $pid = /* generate random string */;
    if (mysqli_stmt_execute ($stmt)) 
        break;  /* success */
    $e = mysqli_stmt_errno ($stmt);
    if ($e !== 1062)
        break;  /* other error */
}
mysqli_stmt_close ($stmt);

if ($e) {
    if ($e === 1062) {
        /* Failed to generate unique PID */
    } else {
        /* Other database error */
    }
} else {
    /* success */
}

如果将PID值设置为8个字符,则将需要一些内容来生成字符串并检查其是否不存在。

$alphabet = range('A','Z');

// get all the PIDs from the database
$sql = "select PID from mytable";

// save those all to an array
$pid_array = results of query saved to array

shuffle($alphabet);
$pid_offer = array_slice($alphabet,0,8);

while(in_array($pid_offer, $pid_array)){
    shuffle($alphabet);
    $pid_offer = array_slice($alphabet,0,8);
}

// found uniuqe $pid_offer...

比赛条件仍然存在。

如果字符串不需要是随机的,则使用ID值(它可能是一个自动递增的整数),并从10000000开始计数。

然后只需对该数字中的数字进行简单的A = 1,B = 2,C = 3等替换即可生成您的字符串。

你的旅费可能会改变。

- 标记

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM