Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从数据库表中查找第一个可用标识符_Php_Mysql_Unique_Identifier_Alphanumeric - Fatal编程技术网

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

Php 从数据库表中查找第一个可用标识符,php,mysql,unique,identifier,alphanumeric,Php,Mysql,Unique,Identifier,Alphanumeric,要求查找第一个可用标识符,其中标识符是字母数字字符串,例如: ABC10000 ABC10345 ABC88942 ABC90123 数据库表具有如下结构: id, user, identifier 请注意,alpha分量ABC始终是一致的,不会改变。数字分量应介于10000和99999之间 如何最好地解决这个问题?这看起来不像是一个过于复杂的问题——只使用MySQL或SQL和PHP的组合来寻找最简单的解决方案。当前的解决方案将数据库中的每条记录提取到一个数组中,然后从10000开始循环,预

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

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 ;

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

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

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

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

从编辑中重新考虑这一点,您应该按照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'");
$identifier=0;
$i=mysql_查询(“从最后一个_标识符中选择标识符”);
如果($row=mysql\u fetch\u assoc($i))$identifier=$row[“identifier”];
如果($identifier<10000)$identifier=10000;
做{
$identifier+=1;
$result=mysql\u查询(“
将IGNORE插入表(id、用户、标识符)
值(“[…]”、“[…]”,
“ABC”.str_pad($identifier,5,“0”,str_pad_LEFT)。”
)");
如果(mysql_受影响的_行($result)<1)继续;
}while(假);
mysql_查询(“更新上一个_标识符集标识符=“$identifier”);

当然,您需要在标识符字段上添加一个
唯一的
索引。

在编辑过程中重新考虑这一点,您应该使用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'");
$identifier=0;
$i=mysql_查询(“从最后一个_标识符中选择标识符”);
如果($row=mysql\u fetch\u assoc($i))$identifier=$row[“identifier”];
如果($identifier<10000)$identifier=10000;
做{
$identifier+=1;
$result=mysql\u查询(“
将IGNORE插入表(id、用户、标识符)
值(“[…]”、“[…]”,
“ABC”.str_pad($identifier,5,“0”,str_pad_LEFT)。”
)");
如果(mysql_受影响的_行($result)<1)继续;
}while(假);
mysql_查询(“更新上一个_标识符集标识符=“$identifier”);

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

您必须自联接表并在联接表中查找第一个空值

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


编辑 关于ncatnow的一些“特色”的评论。在子选择的帮助下,可以对具有默认值的
'ABC'
联合进行轻微调整

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

您必须自联接表,并在联接表中查找第一个空值

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


编辑 关于ncatnow的一些“特色”的评论。在子选择的帮助下,可以对具有默认值的
'ABC'
联合进行轻微调整

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

类似于@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

与@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

它会永远是最后一张唱片吗?或者您可能会有两个值之间的免费id,即abc10000、abc10002,您需要10001?谢谢-我已经在上面澄清了。它将是第一个可用的“缺失”标识符。@HerrSerker-这是一个错误的评论。也许标识符是一个糟糕的选择(事实上,字段名是
value
)。如果你愿意详细说明的话?它会永远是最后一张唱片吗?或者您可能会有两个值之间的免费id,即abc10000、abc10002,您需要10001?谢谢-我已经在上面澄清了。它将是第一个可用的“缺失”标识符。@HerrSerker-这是一个错误的评论。也许标识符是一个糟糕的选择(事实上,字段名是
value
)。如果您想详细说明一下的话,
id
字段是自动递增的,实际上每次都会增加4个-显然是为了帮助复制,但这不是重点。你的答案很有趣,但我不同意使用记录id来做这个。表结构不会改变-我的问题是如何使用当前的结构、数据和限制查找缺少的标识符。
id
字段是自动递增的,实际上每次递增4个-显然是为了帮助复制,但这不是重点。你的答案很有趣,但我不同意使用记录id来做这个。表结构不会改变-我的问题是如何使用当前结构、数据和限制查找缺少的标识符。这看起来很接近,但没有返回正确的结果-我得到了
ABC1
。它使用的是主键,而不是
标识符
字段。这把小提琴更好地代表了这个问题:@ncatnow我不知道你桌子的确切结构,所以我举了个例子。你必须根据自己的需要来采用它。次要的问题是,如果你有ABC0000,它会将ABC切掉,得到00000,并认为当添加到时,会将其转换为整数0,结果是1,然后在给出ABC1时将其串联。@Kickstart这是真的,但OP确实说,标识符数字不是以开头的