8

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

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

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

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

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

谢谢!

4

5 回答 5

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
于 2012-04-17T10:20:04.037 回答
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

例如:

 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

以此为起点,因为它仍然需要一些调整:

  • 您需要考虑最低可用数字是可能的最低数字的情况。
  • 您需要锁定表以处理并发插入。
  • 在我的电脑里,大桌子慢得要命。
于 2012-04-17T10:41:33.650 回答
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
于 2012-04-17T10:34:13.303 回答
0

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

于 2012-04-17T10:49:35.633 回答
0

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

INSERT INTO xx (id, ...) VALUES (find_first_hole(), ...)
于 2012-04-17T10:21:31.367 回答