在MySQL中删除后自动递增

我有一个主键字段有AUTO_INCREMENT的MySQL表。 在阅读其他文章后,我注意到有同样问题和不同答案的人。 有些人build议不要使用这个function,有些则说不能“固定”。

我有:

table: course fields: courseID, courseName 

例如:表中logging的数量:18.如果我删除logging16,17和18 – 我期望input的下一个logging具有16的courseID,但是它将是19,因为最后input的courseID是18。

我的SQL知识并不奇妙,但无论如何刷新或更新这个计数与查询(或phpMyAdmin接口中的设置)?

该表格将与数据库中的其他人相关联。


鉴于所有的build议,我决定忽略这个“问题”。 我会简单地删除和添加logging,同时让自动增量做它的工作。 我想这个数字并不重要,因为它只被用作唯一标识符,并没有(如上所述) 业务意义。

对于那些可能与我原来的post混淆的人:我不想用这个字段来知道我有多lesslogging。 我只是希望数据库看起来整洁,并且有更多的一致性。

你试图做的事听起来很危险,因为这不是AUTO_INCREMENT使用目的。

如果您确实想要find最低的未使用的密钥值,请不要使用AUTO_INCREMENT ,并手动pipe理您的密钥。 但是,这不是一个推荐的做法。

退一步,问“ 为什么你需要回收键值? ”无符号INT (或BIGINT )不提供足够大的密钥空间?

在应用程序的整个生命周期中,你是否真的有超过18,446,744,073,709,551,615独特logging?

 ALTER TABLE foo AUTO_INCREMENT=1 

如果您删除了最近的条目,应该将其设置为使用下一个最低的条目。 如在,只要没有19,删除16-18将重置自动增量使用16。


编辑:我错过了关于phpmyadmin的一点。 你也可以在那里设置。 转到表格屏幕,然后单击操作选项卡。 这里有一个AUTOINCREMENT字段,您可以手动设置任何您需要的字段。

数据库中的主要自动增量键用于唯一标识给定的行,不应给予任何业务含义。 因此,保持主键courseOrder并添加另一个名为例如courseOrder列。 然后,当您从数据库中删除logging时,可能需要发送额外的UPDATE语句,以减lesscourseOrder大于当前正在删除的行的所有行的courseOrder列。

作为一个方面说明,你不应该修改关系数据库中的主键的值,因为可能有其他表引用它作为外键,修改它可能会违反引用约束。

试试:

SET @num:= 0;

UPDATE your_table SET id = @num:=(@ num + 1);

ALTER TABLE tableName AUTO_INCREMENT = 1;

这将重置autoincremented值,然后计数每一行,而为它创build一个新的值。

例如:之前

  • 1:这里第一个值
  • 2:这里的第二个值
  • X:删除的值
  • 4:桌子的其余部分
  • 5:其余的rest..

所以表中将显示数组:1,2,4,5

例如:AFTER(如果您使用此命令,您将获得)

  • 1:这里第一个值
  • 2:这里的第二个值
  • 3:桌子的其余部分
  • 4:其余的rest

没有删除的值的痕迹,其余的增量继续这个新的计数。

  1. 如果你的代码的某处使用自动增量值…也许这个归因会导致问题。
  2. 如果你不在代码中使用这个值,一切都应该没问题。

您不应该依靠AUTO_INCREMENT ID来告诉您表中有多less条logging。 你应该使用SELECT COUNT(*) FROM course 。 ID是唯一标识课程的地方,可以用作其他表格的参考,所以你不应该重复ID,也不应该试图重新设置自动增量字段。

你可以像这样selectID:

 set @rank = 0; select id, @rank:=@rank+1 from tbl order by id 

结果是一个ID列表,以及它们在序列中的位置。

你也可以像这样重置ID:

 set @rank = 0; update tbl a join (select id, @rank:=@rank+1 as rank from tbl order by id) b on a.id = b.id set a.id = b.rank; 

你也可以打印出第一个未使用的ID,如下所示:

 select min(id) as next_id from ((select a.id from (select 1 as id) a left join tbl b on a.id = b.id where b.id is null) union (select min(a.id) + 1 as id from tbl a left join tbl b on a.id+1 = b.id where b.id is null)) c; 

在每次插入之后,可以重置auto_increment:

 alter table tbl auto_increment = 16 

或者在插入时显式设置id值:

 insert into tbl values (16, 'something'); 

通常这不是必须的,你有count(*)和能够在你的结果集中创build一个排名数字。 一个典型的排名可能是:

 set @rank = 0; select a.name, a.amount, b.rank from cust a, (select amount, @rank:=@rank+1 as rank from cust order by amount desc) b where a.amount = b.amount 

按消费金额排列的客户。

我有一个非常简单但棘手的方法。

在删除行时,您可以将这些ID保存到另一个临时表中。 之后,当您将新数据插入到主表中时,您可以search并从临时表中selectID。 所以在这里使用一个检查。 如果临时表没有ID,则计算主表中的最大ID,并将新ID设置为: new_ID = old_max_ID+1

注意:这里不能使用自动增量function。

我来到这里寻找标题问题"MySQL - Auto Increment after delete"的答案,但我只能find答案

  • 如何从MySQL表中删除某些行?
  • 如何重置MySQL中的AUTO_INCREMENT?

通过使用类似的东西:

 DELETE FROM table; ALTER TABLE table AUTO_INCREMENT = 1; 

请注意Darin Dimitrov的回答很好地解释了AUTO_INCREMENT和它的用法。 在做一些你可能会后悔的事情之前,先看看那里。

PS:问题本身就是更多"Why you need to recycle key values?" Dolph的回答涵盖了这一点。

您可以使用您的mysql客户端软件/脚本在删除所需logging后指定主键的起始位置。

你想要做的是非常危险的。 仔细想想这个。 自动增量的默认行为有很好的理由。

考虑这个:

在与另一个表具有关系的表中删除一条logging。 由于审计原因,第二张表中的相应logging不能被删除。 该logging从第一个表中变成孤立的。 如果新logging插入到第一个表中,并且使用顺序主键,则此logging现在链接到孤儿。 显然,这是不好的。 通过使用自动递增的PK,始终保证以前从未使用过的ID。 这意味着孤儿是孤儿,这是正确的。

我可以想到很多场景,尤其是在移植或开发过程中,您可能需要这样做。 例如,我现在必须通过交叉连接两个现有表(作为一个复杂的设置过程的一部分)来创build一个新表,然后我需要在事件之后添加一个主键。 您可以删除现有的主键列,然后执行此操作。

 ALTER TABLE my_table ADD `ID` INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`ID`); 

对于直播系统来说,这不是一个好主意,特别是如果有其他表格指向外键。

实际上有办法解决这个问题。 首先删除auto_incremented主键列,然后再次添加,如下所示:

 ALTER TABLE table_name DROP column_name; ALTER TABLE table_name ADD column_name int not null auto_increment primary key first; 
 if($id == 1){ // deleting first row mysqli_query($db,"UPDATE employees SET id=id-1 WHERE id>1"); } else if($id>1 && $id<$num){ // deleting middle row mysqli_query($db,"UPDATE employees SET id=id-1 WHERE id>$id"); } else if($id == $num){ // deleting last row mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num"); } else{ echo "ERROR"; } mysqli_query($db,"ALTER TABLE employees AUTO_INCREMENT = $num"); 

你可以考虑在删除后做一个触发器,这样你可以更新autoincrement的值和所有看起来不像你想看到的行的ID值。

因此,您可以使用同一个表格,并且每当您删除一行触发器将修复它时,自动增量将自动修复。

这里是一个解决你的问题的function

  public static void fixID(Connection conn, String table) { try { Statement myStmt = conn.createStatement(); ResultSet myRs; int i = 1, id = 1, n = 0; boolean b; String sql; myRs = myStmt.executeQuery("select max(id) from " + table); if (myRs.next()) { n = myRs.getInt(1); } while (i <= n) { b = false; myRs = null; while (!b) { myRs = myStmt.executeQuery("select id from " + table + " where id=" + id); if (!myRs.next()) { id++; } else { b = true; } } sql = "UPDATE " + table + " set id =" + i + " WHERE id=" + id; myStmt.execute(sql); i++; id++; } } catch (SQLException e) { e.printStackTrace(); } } 

它绝对不值得推荐。 如果你有一个有多个表的大型数据库,你可能已经在表2中保存了一个用户id。如果你重新安排了表1,那么预期的用户ID可能不会成为目标表2的ID。