因此,以某种方式使用名为id的AUTO_INCREMENT字段输入数据时,我发现数据实际上缺少某些行。那就是会有像:
这样的行 ID COL1 COL2
2000 data data
2001 data data
2003 data data
我的问题不在于如何发生这种跳过(我稍后会查看我的代码以找到该错误),而是如何查找跳过的行并修复此问题。所以问题是:
1)我可以用什么SQL命令来查找跳过的ID,这样我至少知道它们在哪里?
2)是否有任何SQL voodoo可用于在跳过一个ID之后向上移动所有行,以便填写缺少的ID?即。移动2003年到2002年和2004年到2003年等等
编辑:
这不是关于差距如何发生的问题,而是如何解决问题。我向你保证,这个表上没有删除只有其他程序插入。我知道那里肯定有一个bug。问题是如何在我当前的实时系统上修复数据。
答案 0 :(得分:3)
有几个原因,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 Fiddle Here 强>
同样,所有“跳过”值的警告都不是问题,重置id值会导致大问题(如上所述)。
要重置表的AUTO_INCREMENT值,它是一个简单的ALTER TABLE语句。如果您尝试将其设置为低于最大ID值,MySQL将使用最大id值。所以,你可以
ALTER TABLE mytable AUTO_INCREMENT = 1;
此语句不会更改现有行,只是将自动增量值设置为最小值,这样检索到的下一个自动增量将高于当前表中的最大ID值。
要回答第一个问题,要获取“跳过的”id值列表会更加困难,因为它们没有行源。
如果我们只是想检查是否“跳过”任何id值,我们可以使用别名为u的内联视图中的查询(来自上面的UPDATE语句)。我们将UPDATE更改为SELECT,只过滤掉id值与(generate)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
如果该查询没有返回任何行,则没有“跳过”值。
答案 1 :(得分:2)
根据您对我的评论的评论,解决方案是简单地重置自动增量列,如下所示:How to reset AUTO_INCREMENT in MySQL?
ALTER TABLE tablename AUTO_INCREMENT = 1
答案 2 :(得分:1)
正如其他人尝试过但未能告诉您的那样,自动增量列中的间隙不是错误,这是正常的行为(它可能发生在像回滚插入那样简单的事情上)。如果您的应用程序因间隙而窒息,那么应用程序就会被窃听。
您不能尝试使您的ID顺序,您必须专注于让您的应用程序正确处理这些差距。
如果您绝对需要这些值是顺序的,那么您根本不应使用自动增量列(或者可能添加手工制作的order
列。)
答案 3 :(得分:0)
对于问题1:
嗯..您可以做一个简单的查询来计算id的行。像这样:
从id
在2000年和2003年之间的your_table
中选择计数(id
);
该查询的结果应返回4。
问题2:
一个简单的alter table自动递增即可。