在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