我有一个看起来像这样的SQL列。
注意1100s和2000s中是否有数字(1101-1123没有显示,但它们存在)。我编写了一个脚本,以便注册某个组的用户将获得与该组相对应的登录信息。因此,如果他们在基本组中注册,他们将在1100年代首次登录。如果他们在温和的团体中注册,那么他们将在2000年代获得第一个可用的登录。假设用户AAL2002被删除,下一个加入的人应该登录2002而不是2007(以便自动填充空白)。
现在我有一个PHP脚本,它试图查看所有内容并为它们提供一个新的,未使用的登录。问题是它重复了一些登录。有没有其他方法可以用PHP和SQL做到这一点?
如果您认为可以修复,那么这是我可怕的,令人困惑的代码:
$husers = Query::runQuery("SELECT * FROM `users` WHERE `group`=? AND `login` NOT BETWEEN 'AAL1000' AND 'AAL1010'", array($post['group']));
$i = 0;
$f = false;
do
{
$baseid = (substr($users[$i]['login'], 3)) + 1;
if($baseid != substr($users[$i+1]['login'], 3))
{
$checkid = Query::runQuery("SELECT * FROM `users` WHERE `login`=?", array("AAL".$baseid));
if($checkid[0]['login'] != "AAL".$baseid)
{
$f = true;
}
}
$i++;
}
答案 0 :(得分:0)
如果您有多个用户同时注册(竞争条件),则根本不起作用。您可以使用数据库事务解决此问题。 最重要的是,您应该使用SQL函数进行查找并为您的用户注册下一个免费ID。与事务一起,这将为您提供一个解决方案,即使您的脚本一次被多个人调用也能正常工作。
在mysql中,通常只使用和自动增加列来避免这种问题。在大多数其他数据库上,如果不使用连续整数列,则必须采取严格措施。
答案 1 :(得分:0)
鉴于:
CREATE TABLE login (
login VARCHAR(4)
);
INSERT INTO login (login)
VALUES ('1100'), ('1101'), ('1102'), ('1106'), ('1107');
查询:
SELECT MIN(login) + 1 AS result FROM (
SELECT login,
(SELECT MIN(l2.login) FROM login l2 WHERE l2.login = l.login + 1) AS next
FROM login l
HAVING next IS NULL
) AS list;
给出以下结果:
+--------+
| result |
+--------+
| 1103 |
+--------+
我的示例仅使用alpha + decimal字段的整数部分。这使我无法进行substring operations,根据前缀(" AAL11
"," AAL20
")和最终的演员表(可能不会)进行分组我用varchar演示了必要但是仍然显示了可以完成的方式。我把它留作练习。
如前所述,您只能一起运行lookup + insert操作。这意味着您需要将此作为应用程序中的原子操作(通常称为事务,但我不是指SQL事务)。