从数据库表中查找第一个可用标识符

时间:2014-04-04 11:12:16

标签: php mysql unique identifier alphanumeric

要求是找到第一个可用的标识符,其中标识符是字母数字字符串,例如:

ABC10000
ABC10345
ABC88942
ABC90123

数据库表具有如下结构:

id, user, identifier

请注意,alpha组件ABC始终保持一致,并且不会发生变化。数字组件应介于10000和99999之间。

如何最好地解决这个问题?它似乎不是一个过于复杂的问题 - 使用MySQL或SQL和PHP的组合寻找最简单的解决方案。当前的解决方案将数据库中的每条记录拉入一个数组,然后从10000开始循环,前置ABC并检查可用性,这似乎可以显着改善。


编辑:原始问题不够明确,因为已经分配了一定数量的标识符,我希望填补空白。从我提供的短名单中,下一个可用的是ABC10001。然而,最终它将是ABC10346,然后是ABC88943等等


编辑:抱歉结构不合理的问题。为了避免任何进一步的混淆,这里是实际的表结构:

CREATE TABLE IF NOT EXISTS `User_Loc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user` int(11) DEFAULT NULL,
  `value` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UNIQ_64FB41DA17323CBC` (`user`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4028 ;

4 个答案:

答案 0 :(得分:3)

您必须自己加入表并在联接表中查找第一个NULL值

SELECT CONCAT('ABC', SUBSTRING(t1.value, 4)+1) AS next_value
FROM test t1
LEFT JOIN test t2 on SUBSTRING(t1.value, 4)+1 = SUBSTRING(t2.value, 4)
WHERE ISNULL(t2.value)
ORDER BY t1.value ASC
LIMIT 1

http://sqlfiddle.com/#!2/d69105/22


修改

关于ncatnow的一些'专业'的评论。在子选择的帮助下可以做出轻微的调整,以消除'ABC'UNION的默认值

SELECT 
  CONCAT('ABC', t1.value+1) AS next_value

FROM 
((SELECT '09999' AS value) UNION (SELECT SUBSTRING(value, 4) AS value FROM test)) t1
LEFT JOIN 
((SELECT '09999' AS value) UNION (SELECT SUBSTRING(value, 4) AS value FROM test)) t2 
  ON t1.value+1 = t2.value

WHERE 
  ISNULL(t2.value) 
  AND t1.value >= '09999'

ORDER BY t1.value ASC
LIMIT 1

http://sqlfiddle.com/#!2/28acf6/50

答案 1 :(得分:2)

与@HerrSerker的上述回复类似,但这将处理现有的标识符,其中数字部分以零开头。

SELECT CONCAT('ABC',SUBSTRING(CONCAT('00000', CAST((CAST(SUBSTRING(a.identifier, 4) AS SIGNED) + 1) AS CHAR)), -5)) AS NextVal
FROM SomeTable a
LEFT OUTER JOIN SomeTable b
ON b.identifier = CONCAT('ABC',SUBSTRING(CONCAT('00000', CAST((CAST(SUBSTRING(a.identifier, 4) AS SIGNED) + 1) AS CHAR)), -5))
WHERE b.identifier IS NULL
ORDER BY NextVal
LIMIT 1

答案 2 :(得分:0)

我想到的是一个包含所有标识符的表并使用此sql

SELECT identifier FROM allIdentifiersTable WHERE identifier NOT IN (SELECT identifier FROM yourTable) LIMIT 1

答案 3 :(得分:0)

从编辑中重新考虑这一点,你应该去PHP路线并添加另一个表或其他方法来存储最后一个填充的id:

$identifier = 0;
$i = mysql_query("SELECT identifier FROM last_identifier");
if ($row = mysql_fetch_assoc($i)) $identifier = $row["identifier"];
if ($identifier < 10000) $identifier = 10000;

do {
    $identifier += 1;
    $result = mysql_query("
         INSERT IGNORE INTO table (id, user, identifier)
         VALUES ('[...]', '[...]',
         'ABC" . str_pad($identifier, 5, "0", STR_PAD_LEFT) . "'
    )");
    if (mysql_affected_rows($result) < 1) continue;
} while (false);

mysql_query("UPDATE last_identifier SET identifier = '$identifier'");

当然,您需要在标识符字段中添加UNIQUE索引。