在MySQL中查找下一个可用的id

时间:2009-09-10 13:46:05

标签: sql mysql

我必须在MySQL数据库中找到下一个可用的id(如果数据库中有5个数据,我必须得到下一个可用的插入位置,即6)。我怎样才能做到这一点? 我使用过MAX(id),但是当我从数据库中删除一些行时,它仍然保留了未更新的旧最大值。

15 个答案:

答案 0 :(得分:85)

更新2014-12-05:由于Simon(接受)答案以及Diego的评论中提出的原因,我不推荐这种方法。请使用以下查询,风险自负。

我在mysql开发者网站上找到的最短的一个:

SELECT Auto_increment FROM information_schema.tables WHERE table_name='the_table_you_want'

请注意,如果您拥有相同表的数据库很少,则还应指定数据库名称,如下所示:

SELECT Auto_increment FROM information_schema.tables WHERE table_name='the_table_you_want' AND table_schema='the_database_you_want';

答案 1 :(得分:20)

我认为您无法确定下一个 ID,因为有人可能会在您要求下一个ID之后插入新行。你至少需要一个交易,如果我没弄错,你只能得到在>插入之后使用的实际ID,至少这是处理它的常用方法 - 请参阅{{3 }}

答案 2 :(得分:17)

除了Lukasz Lysik的回答 - LEFT-JOIN类型的SQL 据我所知,如果有id:1,2,4,5它应该返回3。

SELECT u.Id + 1 AS FirstAvailableId
FROM users u
LEFT JOIN users u1 ON u1.Id = u.Id + 1
WHERE u1.Id IS NULL
ORDER BY u.Id
LIMIT 0, 1

希望它能帮助一些游客,虽然帖子相当陈旧。

答案 3 :(得分:11)

鉴于你在评论中所说的话:

  

我的id coloumn是自动增量我必须获取id并将其转换为另一个base.So我需要在插入之前获得下一个id因为转换代码也将被插入。

有一种方法可以做你正在问的问题,就是在实际插入之前询问表格下一个插入行的id

SHOW TABLE STATUS WHERE name = "myTable"

该结果集中将有一个名为“Auto_increment”的字段,它告诉您下一个自动增量值。

答案 4 :(得分:10)

据我所知,如果有id:1,2,4,5它应该返回3.

SELECT t1.id + 1
FROM theTable t1
WHERE NOT EXISTS (
    SELECT * 
    FROM theTable t2
    WHERE t2.id = t1.id + 1
)
LIMIT 1

答案 5 :(得分:4)

你说:

  

我的id coloumn是我自动增量   获取id并将其转换为   另一个基地。所以我需要得到下一个   插入之前的id导致转换代码   也将被插入。

你所要求的是非常危险的,会导致竞争状况。如果你的代码由不同的用户同时运行两次,他们将获得6,他们的更新或插入将互相遍历。

我建议你改为INSERT到表中,使用LAST_INSERT_ID()得到auto_increment值,然后用UPDATE行来设置你拥有的值取决于auto_increment值

答案 6 :(得分:3)

如果要选择第一个间隙,请使用:

SELECT  @r
FROM    (
        SELECT  @r := MIN(id) - 1
        FROM    t_source2
        ) vars,
        t_source2
WHERE   (@r := @r + 1) <> id
ORDER BY
        id
LIMIT   1;

同一查询的语法版本为ANSI

SELECT  id
FROM    mytable mo
WHERE   (
        SELECT  id + 1
        FROM    mytable mi
        WHERE   mi.id < mo.id
        ORDER BY
                mi.id DESC
        LIMIT 1
        ) <> id
ORDER BY
        id,
LIMIT   1

然而,由于MySQL中的优化程序错误,它会很慢。

答案 7 :(得分:1)

如果你真的想在插入行之前计算下一个插入的键(这在我看来不是一个好主意),那么我建议你使用当前使用的最大id加一:

SELECT MAX(id) + 1 FROM table

但我建议您让MySQL自己创建id(通过使用自动增量列)并使用LAST_INSERT_ID()从DBMS获取它。为此,请使用执行插入的事务,然后查询id,如:

INSERT INTO table (col1) VALUES ("Text");
SELECT LAST_INSERT_ID();

returnset现在只包含一列,其中包含新生成的行的id。

答案 8 :(得分:1)

现在回答这个问题为时已晚,但希望这有助于某人。

@Eimantas已经给出了最佳答案,但如果在同一服务器下有两个或多个同名的表,则解决方案不会起作用。

我稍微修改了@ Eimantas的答案,以解决上述问题。

select Auto_increment as id from information_schema.tables where table_name = 'table_name' and table_schema = 'database_name'

答案 9 :(得分:0)

一种方法是将索引设置为自动递增。然后你的SQL语句只是指定NULL,然后SQL解析器为你完成剩下的工作。

INSERT INTO foo VALUES (null);

答案 10 :(得分:0)

如果将这个用于INSERTING一个新记录,你可以使用这样的东西。

(你在评论中说过id是自动递增而另一个表需要下一个ID + 1)

INSERT INTO TABLE2 (id, field1, field2, field3, etc) 
VALUES(
   SELECT (MAX(id) + 1), field1, field2, field3, etc FROM TABLE1
   WHERE condition_here_if_needed
)

这是伪代码,但你明白了

答案 11 :(得分:-1)

许多解决方案的问题是他们只找到下一个“GAP”,而忽略“1”是否可用,或者如果没有任何行,他们将返回NULL作为下一个“GAP”。

以下不仅会找到下一个可用的差距,还会考虑第一个可用的数字是否为1:

SELECT CASE WHEN MIN(MyID) IS NULL OR MIN(MyID)>1
-- return 1 if it's available or if there are no rows yet
THEN
    1
ELSE -- find next gap
    (SELECT MIN(t.MyID)+1
    FROM MyTable t (updlock)
    WHERE NOT EXISTS (SELECT NULL FROM MyTable n WHERE n.MyID=t.MyID+1))
END AS NextID
FROM MyTable

答案 12 :(得分:-1)

这对我来说很有效(MySQL 5.5),也解决了&#34;启动&#34;位置。

SELECT
    IF(res.nextID, res.nextID, @r) AS nextID
FROM
    (SELECT @r := 30) AS vars,
    (
    SELECT MIN(t1.id + 1) AS nextID
    FROM test t1
    LEFT JOIN test t2
      ON t1.id + 1 = t2.id
    WHERE t1.id >= @r
      AND t2.id IS NULL
      AND EXISTS (
          SELECT id
          FROM test
          WHERE id = @r
      )
  LIMIT 1
  ) AS res
LIMIT 1

如前所述,这些类型的查询非常慢,至少在MySQL中。

答案 13 :(得分:-2)

SELECT ID+1 "NEXTID" 
FROM ( 
    SELECT ID from TABLE1 
    WHERE ID>100 order by ID
) "X" 
WHERE not exists (
    SELECT 1 FROM TABLE1 t2
    WHERE t2.ID=X.ID+1
) 
LIMIT 1

答案 14 :(得分:-2)

<?php
Class Database{
    public $db;
    public $host   = DB_HOST;
    public $user   = DB_USER;
    public $pass   = DB_PASS;
    public $dbname = DB_NAME;

    public $link;
    public $error;

    public function __construct(){
        $this->connectDB();
    }
    private function connectDB(){
    $this->link = new mysqli($this->host, $this->user, $this->pass, $this->dbname);
    if(!$this->link){
        $this->error ="Connection fail".$this->link->connect_error;
        return false;
    }
 }

    // Select or Read data

    public function select($query){
        $result = $this->link->query($query) or die($this->link->error.__LINE__);
        if($result->num_rows > 0){
            return $result;
        } else {
            return false;
        }
    }

}
 $db = new Database();
$query = "SELECT * FROM table_name WHERE id > '$current_postid' ORDER BY ID ASC LIMIT 1";
$postid = $db->select($query);
if ($postid) {
  while ($result = $postid->fetch_assoc()) { 
        echo $result['id'];
    } 

  } ?>