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

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

我不认为你可以确定下一个 ID,因为在你询问下一个ID之后,有人可能会插入一个新的行。 你至less需要一个交易,如果我没有弄错,你只能得到插入使用的实际ID,至less这是处理它的常见方式 – 请参阅http://dev.mysql.com/ DOC / refman / 5.0 / EN /获取器唯一id.html

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

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

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

介意你,如果你有less数数据库相同的表,你应该指定数据库名称,如下所示:

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

除了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 

希望它能帮助一些访问者,虽然post比较老。

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

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

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

 SHOW TABLE STATUS WHERE name = "myTable" 

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

据我所知,如果有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 

你说:

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

你所要求的是非常危险的,并会导致竞争条件。 如果你的代码是由不同的用户同时运行两次,他们将得到6,他们的更新或插入将步骤彼此。

我build议你改为INSERT到表中,使用LAST_INSERT_ID()获取auto_increment值,然后UPDATE该行以设置取决于auto_increment值的任何值。

如果你想select第一个缺口,使用这个:

 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优化器错误,它会很慢。

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

 SELECT MAX(id) + 1 FROM table 

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

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

returnset现在只包含一个保存新生成的行的id的列。

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

 INSERT INTO foo VALUES (null); 

如果这是一起使用插入一个新的logging,你可以使用这样的东西。

(你已经在你的评论中说过这个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 ) 

这是伪代码,但你明白了

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

@Eimantas已经给出了最好的答案,但是如果在同一个服务器下有两个或更多同名的表,这个解决scheme将不起作用。

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

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

许多解决scheme的问题是他们只能find下一个“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 

这对我来说很好(MySQL 5.5),也解决了“开始”的问题。

 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 

如前所述,这些types的查询非常缓慢,至less在MySQL中。

 <?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']; } } ?> 
 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