auto_increment 列可能具有“跳过”值的原因有多种...插入失败,INSERT IGNORE ...,INSERT ... ON DUPLICATE KEY,插入中指定的值高于下一个值,行插入又删除,一个ALTER TABLE ... AUTO_INCREMENT =
语句,有各种原因。
AUTO_INCREMENT 向您保证的是一个独特的价值;它不保证不会跳过任何内容。
通常不需要修改 id 值,如果用户和应用程序(合理地)期望 id 值是不可变的,这可能会给用户和应用程序带来一些重大问题。就数据库而言,请注意外键(由 InnoDB 强制执行,或像 MyISAM 那样隐含但不强制执行)或可能触发的触发器等。
为 ID 列设置新值,以便没有“跳过”值(假设不会违反外键约束)
在此示例中,从 id 2001 之后的 id 值开始,这样下一个更高的 id 值(在您的示例中为 2003)将设置为 2002,之后的下一个更高的 id 值将设置为 2003,依此类推...
UPDATE mytable t
JOIN ( SELECT s.id
, @new_id := @new_id + 1 AS new_id
FROM ( SELECT @new_id := 2001 ) i
JOIN ( SELECT r.id
FROM mytable r
WHERE r.id > 2001
ORDER BY r.id
) s
ORDER BY s.id
) u
ON t.id = u.id
SET t.id = u.new_id
SQL小提琴在这里
同样,所有“跳过”值的警告都不是问题,并且重置 id 值可能会导致大问题(如上所述)适用。
要重置表的 AUTO_INCREMENT 值,只需一个简单的 ALTER TABLE 语句。如果您尝试将其设置为低于最大 id 值,MySQL 将使用最大 id 值。所以,你可以
ALTER TABLE mytable AUTO_INCREMENT = 1;
此语句不会更改现有行,它只是将自动增量值设置为最小值,这样检索到的下一个自动增量将比表中当前的最大 id 值高一个。
要回答您的第一个问题,获取“跳过”的 id 值列表比较困难,因为它们没有行源。
如果我们只想检查是否有任何 id 值被“跳过”,我们可以使用别名为 u 的内联视图中的查询(来自上面的 UPDATE 语句)。我们将该 UPDATE 更改为 SELECT,并仅过滤掉 id 值与(生成)new_id 值匹配的行:
SELECT u.*
FROM ( SELECT s.id
, @new_id := @new_id + 1 AS new_id
FROM ( SELECT @new_id := 2001 ) i
JOIN ( SELECT r.id
FROM mytable r
WHERE r.id > 2001
ORDER BY r.id
) s
ORDER BY s.id
) u
WHERE u.id <> u.new_id
ORDER BY u.id
如果该查询没有返回任何行,则没有“跳过”值。