带有标识字段的表:获取已删除记录的ID的最佳SQL查询?

时间:2010-01-18 11:10:16

标签: sql-server tsql identity-column

我有一个带有身份字段的表。从这个表中获取所有已删除记录的ID的最佳SQL查询是什么?

6 个答案:

答案 0 :(得分:2)

您可以使用递归查询:

DECLARE @MaxId int
SELECT @MaxId = SELECT IDENT_CURRENT('MyTable');

WITH Ids AS (
    SELECT 1 AS intId
    UNION ALL
    SELECT intId + 1
    FROM Ids
    WHERE intId < @MaxId
)
SELECT intId
FROM Ids AS i
WHERE NOT EXISTS (
    SELECT NULL FROM MyTable AS m
    WHERE m.intId = i.intId
)
OPTION (MAXRECURSION 0)

如果表非常大,这将不会非常有效。

答案 1 :(得分:2)

完全不同的方法是:

SELECT a.intId, b.intId
FROM MyTable a
    CROSS JOIN MyTable b
WHERE a.intId + 1 < b.intId
    AND NOT EXISTS (
        SELECT NULL FROM MyTable c
        WHERE c.intId > a.intId
            AND c.intId < b.intId
    )

这将提供已删除所有记录的ID对。

因此,如果ID是(1,2,3,6,7,12),它将返回(3,6)和(7,12)。

编辑:

如果表很大,这是非常低效的。以下方法要好得多:

SELECT g.intStartId, MIN(t.intId) AS intEndId
FROM (
    SELECT intId AS intStartId
    FROM MyTable AS a
    WHERE NOT EXISTS (
        SELECT NULL FROM MyTable AS b
        WHERE b.intId = a.intId + 1
    )
) AS g
    CROSS JOIN MyTable AS t
WHERE t.intId > g.intStartId
GROUP BY g.intStartId

因此,我们首先找到标记间隙开始的ID,然后我们找到比标记间隙末尾更大的ID。

答案 2 :(得分:2)

使用数字表左连接并获取所有空数,这使用内置数字表,但最好有自己的

代码看起来像

的示例
create table #bla(id int)

insert #bla values(1)
insert #bla values(2)
insert #bla values(4)
insert #bla values(5)
insert #bla values(9)
insert #bla values(12)



select number from master..spt_values s
left join #bla b on s.number = b.id
where s.type='P'
and s.number < (select MAX(id) from #bla)
and  b.id is null

输出

0 3 6 7 8 10 11

请参阅此处:How to return all the skipped identity values from a table in SQL Server了解更多详情

答案 3 :(得分:1)

一个选项是创建一个临时表/可嵌入SQL语句,其中包含所有可能的ID(this article中列出了一些选项),最多包括表的最大(标识)。

然后,您可以使用您的表从此规范值列表中继续加入,并在右侧的空值上过滤。

答案 4 :(得分:1)

关注顺序ID列的查询是不够的。如果事务失败,ID序列可能会在插入期间跳过数字,因此如果您ID = (1,3)并不意味着ID=2已被删除,则可能已跳过该OUTPUT DELETED.*序列。 您必须使用某些东西来捕获已删除的记录,例如触发器或{{1}} - 或使用某些内容进行比较,如快照,备份和历史记录表。

答案 5 :(得分:0)

一种完全不同的方法,确实需要对您的示例进行重构,不是从表中删除,而是要有一个单独的已删除项ID的表(或者在表中有一个字段显示行的状态) 。因此,您可以选择这些数据。 (这将围绕@ Damir的观察,即你无法区分删除和插入错误。)