【问题标题】:How to ensure no gaps in auto_increment numbers?如何确保 auto_increment 数字没有间隙?
【发布时间】:2016-01-02 18:54:56
【问题描述】:

我有一个关于 auto_incrementing 的问题,这是我的第一个表,它对递增 id* 非常顺利

id*      name
1        name1
2        name2
3        name3
4        name4
5        name5
6        name6

但是当我删除一条记录并插入一条新记录时,id 从 7 开始。

id*      name
1        name1
2        name2
3        name3
5        name5
6        name6
7        name7

这就是我想做的:

id*      name
1        name1
2        name2
3        name3
4        name7
5        name5
6        name6

我想要一个填写每个数字的解决方案,所以如果我删除一行,下一个 autoinc 数字将是我删除的数字,而不是下一个更高的数字。

【问题讨论】:

  • 不,没有办法轻松地重新初始化自动增量项目,这也不是一个好主意,但这里有一些解决方案的当前检查:stackoverflow.com/questions/740358/…
  • 您尝试做的事情并不安全。想象一下,您有另一个带有外键“id”的表。如果您删除一行并尝试将所有其他行快速向上,则表之间的关系将中断。
  • 永远不要乱用自动增量!
  • 我建议您考虑一下您认为自己想要这个的原因,并可能问一个关于那个的问题。
  • 为什么要这样做?它是非标准的,可能有一个不同的解决方案会更好。试着解释为什么你需要这样做

标签: mysql sql


【解决方案1】:

首先,有这些差距是完全好的的。 没有问题。只是你的强迫症迫使你认为这些数字必须遵循一个模式——他们没有。

  • auto_increment 不是 PHP 功能,而是 MySQL 功能
  • auto_increment 确保每一行都有一个唯一数字。它不处理序号
  • auto_increment 在并发环境中安全工作 - 这意味着有很多用户连接到 MySQL 并做一些事情,他们都必须能够处理数据库并且不能获得相同的 id 来识别行。这是通过一个相当复杂的过程完成的,这也是auto_increment 产生差距的原因之一
  • auto_incrementInnoDB 用于磁盘上记录的物理组织——它使用auto_increment 的特性,并且产生的数字比以前大(这就是它的作用,比以前大,不是连续的)。使用它,构建一个 b-tree 并将记录按顺序写入硬盘驱动器上。篡改auto_increment 会使InnoDB 重新平衡树。这意味着如果您弄乱它,它会遍历记录并重新创建索引 - 这是您不想要的。曾经

当您考虑它时,您甚至会从序列号中得到什么?没什么,只是你的大脑可能不会那么痛,因为有一些假想的顺序。

对于序列号,使用触发器来创建它们。 auto_increment 有一份工作,而且只有一份工作 - 产生唯一数字。

【讨论】:

    【解决方案2】:

    如果您想获得看起来像列表的东西,我建议您保留“ID”字段原样并添加另一个字段以用于按数字排序的名称。

    不管怎样,你可以通过这样的查询得到相同的结果:

    SELECT name, @Rk := @Rk+1 AS Rank
    FROM mynamestable, (Select @Rk := 0) AS Rk 
    

    编辑: 此查询将返回表 mynamestable 中字段 name 中的所有记录以及一列(名为 Rank),该列将是数字增量(从 1 开始),因此结果将类似于:

    name    Rank
    Name1    1
    Name2    2
    Name3    3
    

    【讨论】:

    • 嗨,您能更详细地解释一下这个查询在做什么吗?
    • @TobyAllen 我加了一点解释
    • 这如何防止为大量并发请求生成相同的数字?我没有看到任何限制,您显然假设总会有一个人连接到 MySQL 工作。这是一个完全不安全的解决方案。
    • @Mjh 我指出这只是一个列表。它仅返回当前排名。这会在保留 ID 的同时为您提供当前排名。
    • 所以你同意这不是一个可以在并发环境中安全工作的真正答案,对吧?
    【解决方案3】:

    为此,您可以在删除后使用trigger。更新所有大于删除id的id(减1)

    CREATE TRIGGER update_ids AFTER DELETE ON test_table
    FOR EACH ROW SET UPDATE test_table SET id = id - 1 WHERE id > OLD.id;
    

    您还必须reset auto_increment 或为插入编写另一个触发器,它将 id 更新为 max(id)

    【讨论】:

    • 这不是他所追求的,这会破坏不同表上 id 之间的任何链接 这是一个糟糕的想法,即使它可能会解决问题。
    猜你喜欢
    • 2020-04-19
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 2018-09-03
    • 2013-08-14
    相关资源
    最近更新 更多