如何在auto_increment列中找到“holes”?

时间:2012-04-17 10:15:18

标签: mysql sql gaps-and-islands

当我删除时,例如,id 3,我有这个:

id | name
 1 |
 2 |    
 4 |
 5 |
 ...

现在,我想搜索丢失的id,因为我想再次填写id:

INSERT INTO xx (id,...) VALUES (3,...)

有没有办法在auto_increment索引中搜索“漏洞”?

谢谢!

5 个答案:

答案 0 :(得分:16)

您可以找到这样的差距的最大值​​:

select t1.id - 1 as missing_id
from mytable t1
left join mytable t2 on t2.id = t1.id - 1
where t2.id is null

答案 1 :(得分:3)

AUTO_INCREMENT的目的是为您的行生成简单唯一且无意义的标识符。一旦您计划重新使用这些ID,它们就不再是唯一的(至少不会及时),所以我觉得您没有使用正确的工具来完成工作。如果你决定摆脱AUTO_INCREMENT,你可以使用相同的算法完成所有插入。

关于SQL代码,此查询将使现有行与具有下一个ID的行匹配:

SELECT a.foo_id, b.foo_id
FROM foo a
LEFT JOIN foo b ON a.foo_id=b.foo_id-1

E.g:

 1 NULL
 4 NULL
10 NULL
12 NULL
17 NULL
19   20
20 NULL
24   25
25   26
26   27
27 NULL

因此,过滤掉行并获得第一个差距很容易:

SELECT MIN(a.foo_id)+1 AS next_id
FROM foo a
LEFT JOIN foo b ON a.foo_id=b.foo_id-1
WHERE b.foo_id IS NULL

以此为出发点,因为它仍需要一些调整:

  • 您需要考虑最低可用数字是最低可用数字的情况。
  • 您需要锁定表以处理并发插入。
  • 在我的电脑里,它和大桌子一样慢。

答案 2 :(得分:2)

我认为你能做到这一点的唯一方法就是循环: 任何其他解决方案都不会显示大于1的间隙:

insert into XX values (1)
insert into XX values (2)
insert into XX values (4)
insert into XX values (5)
insert into XX values (10)

declare @min int
declare @max int

select @min=MIN(ID) from xx
select @max=MAX(ID) from xx

while @min<@max begin
    if not exists(select 1 from XX where id = @min+1) BEGIN
        print 'GAP: '+ cast(@min +1 as varchar(10))
    END

    set @min=@min+1
end

结果:

GAP: 3
GAP: 6
GAP: 7
GAP: 8
GAP: 9

答案 3 :(得分:0)

首先,我同意你不应该尝试填补漏洞的评论。您将无法使用单个SQL语句找到所有漏洞。你必须循环遍历从1开始的所有可能的数字,直到找到一个洞。您可以编写一个sql函数来为您执行此操作,然后可以在函数中使用它。因此,如果您编写了一个名为find_first_hole的函数,则可以在类似的插入中调用它:

INSERT INTO xx (id, ...) VALUES (find_first_hole(), ...)

答案 4 :(得分:0)

这是一个差距和岛屿问题,请参阅我的(和其他)回复herehere。在大多数情况下,使用递归CTE可以最优雅地解决间隙和岛屿问题,这在mysql中是不可用的。