如何根据查询结果循环我的函数


How to loop my function based on query result

我写了一个函数,它生成一个随机id makeid();。为了确保id是唯一的,我有一个SQL语句来检查id是否已经存在。

$does_id_exist = mysql_query("SELECT COUNT(*) AS count FROM signups WHERE affid='$affid'");
if(mysql_num_rows($does_id_exist) == 1) 
  { 
  #loop function and perform query again
  }
else
  {
  #insert record
  }

所以我在循环函数时遇到了问题。如何循环我的函数makeid()并执行$does_id_exist检查以确保每个ID是唯一的。

--UPDATE——只是澄清一下——我的代码生成了一个类似YES@281E的id,但在我将这个id插入用户记录之前。我只需要验证是否有其他用户已经有了这个id。如果有其他用户有这个id,则该事件必须触发我的函数来创建一个新的id,例如WOW!29E3,并再次检查sql/query,以确保没有其他用户有那个id。如果失败,则继续循环,如果id可用,则结束并插入。

您可以只在数据库表上使用主键,也可以使用类似的东西:

<?php
    // the id to insert
    $newId = null;
    // populate with results from a SELECT `aff_id` FROM `table`
    $currentIds = array(); 
    // prepopulate
    for( $i=0; $i<100000; $i++ )
    {
        $currentIds[] = "STRING_" + rand();
    }
    // generate at least one id
    do
    {
        $newId = "STRING_" + rand();
    }
    // while the id is taken (cached in $currentIds)
    while( in_array($newId, $currentIds) );
    // when we get here, we have an id that's not taken.
    echo $newId;    
?>

输出:

STRING_905649971(运行时间95ms);

我绝对不建议重复运行查询。如果你的流量足够大,也许在插入之前进行最后一次检查。

不要执行COUNT(*),因为你不需要知道有多少行(它应该是0或1,因为你需要Id唯一),所以即使DB找到了你的行,它仍然会检查整个表是否计数。您真的很关心是否有1行,所以只需选择具有该ID的行,这就足够了。您还应该避免使用rand()——正如您所看到的,这并没有帮助,而且在找到"空闲插槽"之前,您无法预测您可以执行多少循环。使用一些可预测的东西,比如日期前缀,或者前缀每天递增。任何有助于缩小数据集的内容。但现在(伪代码!):

$id = null;
while( $id == null ) {
  $newId = 'prefix' . rand();
  mysql_query("SELECT `affid` FROM `signups` WHERE `affid`='${newId}'");
  if( mysql_num_rows() == 0) {
    $id = newId;
    break;
  } 
}

确保数据库已编入索引,以加快速度。

编辑:我同意任何缓存都有助于加快速度(你可以根据@Josh的例子自己轻松添加),但我认为这是在错误的地方修复的。如果可能的话,重新思考生成ID的方式。它并不需要自动递增,但比rand()更可预测的东西会对你有所帮助。如果您的ID不需要容易记忆,并且将其按顺序排列也没有任何安全问题,那么可以使用除10之外的其他基数的数字(即,使用26将使用所有数字+字母,因此您将以PREFIX-AX3TK结尾,因此可以根据您的需要使用字符串,同时您可以轻松地快速生成下一个ID