【问题标题】:generate get next unique number from mysql ID生成从mysql ID获取下一个唯一编号
【发布时间】:2011-05-10 07:45:14
【问题描述】:

我需要为每个用户生成一个唯一的扩展名(这与 ID 是分开的,但工作方式大致相同)该数字应该是 100 或更大,并且可以被覆盖/自定义设置。现在我正在使用下一个 id,如果它小于 100,则添加 100。

因此,如果下一个 id 为 5,则数字为 105,但下一个 id 为 105,则数字仅为 105。问题在于,如果用户之前选择 105,我会让用户选择他们自己的分机在这种情况下,我想让它自动跳到下一个数字 106。现在如果有 105、106 和 108,我想跳到 107,然后跳到 109。这是我用来生成数字的代码.我认为问题出在我的while循环上。我不知道如何让它继续检查唯一的数字。

这是代码,我敢肯定我的事情过于复杂了很多。

$result = mysql_query("SELECT MAX(id) 
                         FROM USERS");
$row = mysql_fetch_row($result);
$sql_extention = intval($row[0]);

//make sure it's at least 100
$extension = ($sql_extension < 100) ? $sql_extension+100 :  $sql_extension;

//check to see if the extention is in use
$qry = "SELECT `extention` 
          FROM users 
         WHERE extention = '$extention'";
$result2 = mysql_query($qry);

//if the extention is in use then find the next available one (this isn't currently working)
if($result2) {
  //get all results greater or equal to our extention
  $qry3 = "SELECT `id`,`extention` 
             FROM admin_users 
            WHERE extention >= '$extention'";

  $result3 = mysql_query($qry3);
  //this loop needs to be rewritten somehow to get the next number by checking if the next number exist if not return that as the extention
  $new_extention = $extention+1;

  while($extention_data = mysql_fetch_array($result3)) {
    if($new_extention != $extention_data['extention']+1) {
      $extention = $new_extention;
    }

  $new_extention++;
}

【问题讨论】:

  • 也许获取所有扩展名的数组,按升序排序并迭代直到找到未使用的数字会起作用吗?我会忘记 100+n 部分的事情;一旦你拥有超过 100 个用户,它就会变得完全多余。

标签: php mysql sql


【解决方案1】:

我想出了这个,还没有彻底测试它,但我认为它应该正确返回下一个可用值

SELECT (a.extention + 1) as avail 
FROM admin_users a LEFT JOIN admin_users b on ( (a.extention + 1) = b.extention )
WHERE a.extention >= 105 and b.extention is null
ORDER BY avail ASC 
LIMIT 1

因此,如果这按预期工作,您根本不需要最后几行代码。

编辑: 修改了查询,因为我意识到我从错误的角度接近它。

【讨论】:

  • 那行不通。它似乎在倒退。它取了最高值并带走了 1。例如,我有一个 9000 的扩展名,它返回 8999 我会玩弄它。看起来很有希望。
  • 啊,我知道发生了什么,我想如果您将&gt;= 更改为&gt; 它将正常工作,因为您已经检查了 105 的存在。
  • 我想我看到了问题所在。扩展名为 9000 的用户是唯一大于 105 的用户
  • 尝试更新后的查询,我从错误的角度接近它
  • @Sabeen 新查询采用最高扩展并加 1。所以在我的例子中,我的扩展从 5 到 9000,你得到 9001,我想得到 106。(谢谢大家你的帮助)
【解决方案2】:

根据我的评论,对 PHP/伪代码示例的伪劣尝试:

//nicer way to get the id of the user you just inserted!
$id = mysql_insert_id();

$sql = "SELECT `extension` FROM users ORDER BY `extension` ASC";
$res = mysql_query($sql);

$i=0;
while($n = mysql_fetch_array($res)){
  if($i==0){
    $i=$n['extension'];
  }
  if($i==$n['extension']){
    $i++;
  } else {
    break;
  }
}

//No existing users, start at 100
if($i==0){
  $i=100;
}

然后使用 $i 作为你的扩展。

【讨论】:

  • 我想提请注意mysql_insert_id():使用SELECT MAX(ID) FROM Table 的OPs 方法虽然简单,但如果在此查询运行之前创建了另一个用户,则会给出不正确的结果。例如,Alice 创建用户#1,Bob 创建用户#2,Alice 查询MAX(ID) 并得到#2,Bob 查询并得到#2,随之而来的是混乱。
  • @Jon 这是在插入之前发生的。我可能应该先做一个 INSERT 然后 UPDATE 解决方案。
  • @BandonRandon:嗯,很有趣。那么,在您的情况下,您可能应该考虑将此过程放入带有事务的存储过程中,以便在您的代码确定 ID 时锁定表。否则,您仍然可以获得如上所述的竞争条件。在快速谷歌上,这个页面描述了风险:weblogs.sqlteam.com/dang/archive/2007/10/28/…
  • @Jon:是的,我知道这需要注意。现在我正在运行 3 次检查。第一个查询按照接受的答案运行。第二个 ajax 检查扩展在客户端是唯一的(在发布之前)。第三次在插入之前在服务器端进行 PHP 检查。
【解决方案3】:

好的,所以您需要比给定数字更高的下一个可用扩展,该数字还没有在数据库中。 因此,理想情况下,您需要数据库中的一个数组,其所有可用扩展都高于给定键的升序排序。然后你从给定的数字加一循环,直到它不匹配。您没有提到最大扩展数。我会这样做:

<?php
$rs = mysql_unbuffered_query("SELECT extention, MAX(extention) FROM admin_users WHERE extention > '$extention' ORDER BY extention ASC");
$unavailable = array();
$max = 0;
while( ($row = mysql_fetch_row($rs)) )
{
    $unavailable[] = $row[0];
    if( !$max ) $max = $row[1];
}
mysql_free_result($rs);
// Optimization for the quite common case where no more extentions are available
if( count($unavailable) > 0 )
{
    while($extention <= $max+1)
    {
        if( !in_array($extention, $unavailable) )
            break;
        $extention++;
    }
}
else
    $extention = $max+1;
// Worst case: $extention now is max + 1 and we looped through almost everything.
?>

【讨论】:

  • 理想情况下,我不会有一个最大 ID,只是允许扩展随着用户 ID 的增加而变大。
  • @bandonrandon 那么你的最大扩展总是当前的最大值。编辑答案。
  • 这似乎没有返回任何东西。
  • 可能会导致您在代码中使用 2 种不同的扩展拼写。无论哪种方式,使用如下查询似乎更可取。
猜你喜欢
  • 2011-05-21
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-06
  • 2013-04-11
  • 2012-02-22
相关资源
最近更新 更多