生成连续的五位字母数字ID

时间:2011-06-13 20:00:20

标签: php mysql algorithm

概述:

下面的函数吐出一个随机ID。我正在使用它来提供识别记录的确认别名。但是,我必须检查碰撞(但不太可能),因为我们只使用五位数长度。使用下面列出的允许字符,它可以达到大约3300万个组合。最终我们将获得500万左右的记录,因此碰撞成为一个问题。

问题:

检查欺骗别名效率低,资源量大。搜索500万条记录很多。特别是当这种搜索由不同的用户同时进行时。

我的问题:

有没有办法'自动增加'此功能允许的组合?意思是我只需要搜索最后一条记录的别名并转到下一个组合?

已确认的限制:

我意识到代码与下面的函数有很大不同。我也意识到mysql具有数字ID的自动增量功能,但该项目需要一个五位数的别名,允许的字符为“23456789ABCDEFGHJKLMNPQRSTUVWXYZ”。我的双手就是这个问题的关键。

我目前的职能:

 public function random_id_gen($length)
 {
     $characters = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
     $max = strlen($characters) - 1;
     $string = '';

     for ($i = 0; $i < $length; $i++) {
         $string .= $characters[mt_rand(0, $max)];
     }

     return $string;
 }

3 个答案:

答案 0 :(得分:5)

为什么不在别名列上创建唯一索引?

CREATE UNIQUE INDEX uniq_alias ON MyTable(alias);

此时您可以尝试插入/更新,如果它返回错误,请生成新别名并重试。

答案 1 :(得分:1)

您真正需要做的是从基数10转换为基数strlen($characters)

PHP附带了一个内置的base_convert函数,但它并没有完全符合您的要求,因为它将使用数字零,一和字母'o',这是您没有的版。因此,您需要一个函数来将base_convert中的值映射到您的值:

function map_basing($number, $from_characters, $to_characters) {
    if ( strlen($from_characters) != strlen($to_characters)) {
       // ERROR!
    }

    $mapped = '';
    foreach( $ch in $number ) {
       $pos = strpos($from_characters, $ch);
       if ( $pos !== false ) {
          $mapped .= $to_characters[$pos];
       } else {
          // ERROR!
       }
    }

    return $mapped;
}

现在你有了:

 public function next_id($last_id)
 {
    $my_characters = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
    $std_characters ='0123456789abcdefghijklmnopqrstuv';

    // Map from your basing to the standard basing.
    $mapped = map_basing($last_id, $my_characters, $std_characters);

    // Convert to base 10 integer and increment.
    $intval = base_convert($mapped, strlen($my_characters), 10);
    $intval++;

    // Convert to standard basing, then to our custom basing.
    $newval_std = base_convert($intval, 10, strlen($my_characters));
    $newval = map_basing($newval_std, $std_characters, $my_characters);


    return $newval;
 }

可能会出现一些语法错误,但你应该得到它的要点。

答案 2 :(得分:0)

你可以滚动自己的自动增量。这可能是相当低效的,因为你必须弄清楚你的增量在过程中的位置。例如,如果您将随机字符串中的位置指定为整数,并以(0)(0)(0)(0)(0)开头,它将等同于22222作为ID。然后得到下一个,只需将最后一个值递增到(0)(0)(0)(0)(1),它将转换为22223.如果最后一个值达到你的字符串长度,则将其设为0并增加倒数第二个等等......它不是随机的,但它会增加并且是唯一的。