在MySQL中删除后自动递增

时间:2010-02-06 18:21:01

标签: sql mysql primary-key auto-increment

我有一个MySQL表,主表字段为AUTO_INCREMENT。 在阅读了这里的其他帖子之后,我注意到有相同问题并且答案各不相同的人。有些人建议不要使用此功能,其他人说它不能“修复”。

我有:

table: course
fields: courseID, courseName

示例:表格中的记录数量:18。如果我删除记录16,17和18 - 我希望输入的下一条记录的课程ID为16,但是它将是19,因为最后输入的课程ID是18

我的SQL知识并不令人惊讶,但无论如何使用查询(或phpMyAdmin界面中的设置)刷新或更新此计数?

此表将与数据库中的其他人相关。


鉴于所有的建议,我决定忽略这个'问题'。我将简单地删除并添加记录,同时让自动增量完成它的工作。我想这个数字是多少并不重要,因为它只被用作唯一标识符,并且没有(如上所述) business 的意思。

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

18 个答案:

答案 0 :(得分:66)

您尝试做的事情听起来很危险,因为这不是AUTO_INCREMENT的预期用途。

如果您确实想要找到最低的未使用键值,请不要使用AUTO_INCREMENT,并手动管理您的键。但是,这不是推荐的做法。

退后一步并询问“为什么需要回收键值?”未签名的INT(或BIGINT)是否提供足够大的密钥空间?

在申请的有效期内,您真的会有超过18,446,744,073,709,551,615个独特记录吗?

答案 1 :(得分:34)

ALTER TABLE foo AUTO_INCREMENT=1

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


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

答案 2 :(得分:16)

数据库中的主要自动增量键用于唯一标识给定行,不应给出任何 business 含义。因此,保持主键不变,并添加另一个名为courseOrder的列。然后,当您从数据库中删除记录时,您可能希望发送一个额外的UPDATE语句,以便减少courseOrder列的courseOrder列,其中{{1}}大于您当前正在删除的行。{/ p>

作为旁注,您不应该修改关系数据库中主键的值,因为可能有其他表将其作为外键引用,并且修改它可能违反引用约束。

答案 3 :(得分:9)

尝试:

  

SET @num:= 0;

     

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

     

ALTER TABLE tableName AUTO_INCREMENT = 1;

重置自动增量值,然后在为其创建新值时计算每一行。

示例:之前

  • 1:这里的第一个值
  • 2:这里的第二个值
  • X:已删除的值
  • 4:表格的其余部分
  • 5:剩下的其余的......

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

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

  • 1:这里的第一个值
  • 2:这里的第二个值
  • 3:表格的其余部分
  • 4:剩下的其余

没有删除值的痕迹,其余的增量继续使用此新计数。

BUT

  1. 如果您的代码某处使用了自动增量值...也许此归因会导致问题。
  2. 如果您不在代码中使用此值,则一切正常。

答案 4 :(得分:3)

您不应该依赖AUTO_INCREMENT ID来告诉您表中有多少条记录。您应该使用SELECT COUNT(*) FROM course。 ID用于唯一标识课程,可用作其他表格中的参考,因此您不应重复ID,也不应寻求重置自动增量字段。

答案 5 :(得分:2)

您可以像这样选择ID:

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

或在执行insert时显式设置id值:

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

通常这不是必需的,您有count(*)并且能够在结果集中创建排名编号。典型的排名可能是:

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
客户按消费金额排名。

答案 6 :(得分:2)

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

使用类似的东西:

DELETE FROM table;
ALTER TABLE table AUTO_INCREMENT = 1;

请注意Darin Dimitrov's answer非常好地解释AUTO_INCREMENT及其用法。做一些你可能会后悔的事情,看看那里。

PS:问题本身更多"Why you need to recycle key values?"Dolph's answer涵盖了这一点。

答案 7 :(得分:1)

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

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

注意:你不能在这里使用自动增量功能。

答案 8 :(得分:1)

我可以考虑许多可能需要执行此操作的方案,尤其是在迁移或开发过程中。例如,我现在必须通过交叉连接两个现有表来创建一个新表(作为复杂设置过程的一部分),然后我需要在事件之后添加一个主键。您可以删除现有的主键列,然后执行此操作。

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

对于实时系统,这不是一个好主意,特别是如果有其他表指向外键的话。

答案 9 :(得分:1)

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

ALTER TABLE table_name DROP column_name;
ALTER TABLE table_name ADD column_name int not null auto_increment primary key first;

答案 10 :(得分:0)

这是解决您问题的步骤。

在您的 .php 文件中,只需添加以下给出的查询:

<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "";

$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
      die("Connection failed: " . $conn->connect_error);
}

//write the number or id you want to start with the next user in AUTO_INCREMENT    
$sql = "ALTER TABLE `table_name` AUTO_INCREMENT = number";
$conn->query($sql);
?> 

希望你的问题得到解决。

答案 11 :(得分:0)

MYSQL查询 自动增量解决方案。当您在软件测试阶段插入许多记录时,它可以完美工作。现在,您要向客户端实时启动应用程序,并且要从1开始自动递增。

为了避免任何不必要的问题,为了更安全 首先导出.sql文件。
然后按照以下步骤操作:

  • 步骤1) 首先创建现有表的副本 MySQL命令创建副本:

    CREATE TABLE new_Table_Name  SELECT * FROM existing_Table_Name;
    

    使用约束以外的所有行创建表的精确副本。
    它不会将“自动增量”和“主键”之类的约束复制到new_Table_name

  • 步骤2) 删除所有行如果未在测试阶段插入数据,则该行将无用。 如果数据很重要,则直接转到步骤3。

    DELETE from new_Table_Name;
    
  • 步骤3)要添加约束,请转到表的结构

    • 3A)从“更多”选项中添加主键约束(如果需要)。
    • 3B)从“更改”选项中添加“自动增量”约束。对于此集合,定义为None的值。
    • 3C)删除existing_Table_Name和
    • 3D)将new_Table_Name重命名为existing_Table_Name。

现在它将完美运行。新的第一条记录将在“自动增量”列中获得第一值。

答案 12 :(得分:0)

这是一个解决问题的功能

    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();
    }
}

答案 13 :(得分:0)

绝对不值得推荐。如果你有一个包含多个表的大型数据库,你可能已经在表2中将userid保存为id。如果重新排列表1,那么预期的用户ID可能不会最终成为预期的表2 id。

答案 14 :(得分:0)

您可以考虑在删除后进行触发,这样您就可以更新自动增量的值以及看起来不像您想看到的所有行的ID值。

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

答案 15 :(得分:0)

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");

答案 16 :(得分:0)

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

考虑一下:

在一个与另一个表有关系的表中删除记录。出于审计原因,无法删除第二个表中的相应记录。该记录从第一个表变为孤立。如果将新记录插入到第一个表中,并使用顺序主键,则此记录现在链接到孤立。显然,这很糟糕。通过使用自动递增的PK,始终保证以前从未使用过的id。这意味着孤儿仍然是孤儿,这是正确的。

答案 17 :(得分:0)

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