1

我有一个 PK 增长相当快的表,但是由于行被相当一致地删除,它很快就变成了一个非常稀疏的表:

   ID     VALUE
 ----------------
   1     'Test'
   5     'Test 2'
   24    'Test 3'
   67    'Test 4'

有没有一种方法可以自动在缺少的 ID 中插入下一个值,这样我就不会将该 ID 变得非常大?例如,我想插入 ID 为 2 的“测试 5”。

4

4 回答 4

2

我不是建议做你想做的事,但如果你想这样做,这就是方法。我只是在回答问题,而不是解决问题。

在你的过程中,你会在这样做的时候锁定你的桌子,这样你就不会偷偷溜进来。通过使用链接这个:

EXEC @result = sp_getapplock @Resource = @LockResource, 
                                 @LockMode = 'Exclusive'

EXEC sp_releaseapplock @Resource = @LockResource

桌子

DECLARE @table TABLE ( id INT, val VARCHAR(20) )

数据

INSERT  INTO @table
        (
          id,
          val
        )
        SELECT  1,
                'Test'
        UNION ALL
        SELECT  2,
                'Test'
        UNION ALL
        SELECT  5,
                'Test 2'
        UNION ALL
        SELECT  24,
                'Test 3'
        UNION ALL
        SELECT  67,
                'Test 4' 

查询

INSERT  INTO @table
        SELECT TOP 1
                id + 1,
                'TEST'
        FROM    @table t1
        WHERE   NOT EXISTS ( SELECT TOP 1
                                    1
                             FROM   @table
                             WHERE  id = t1.id + 1 )
        ORDER BY id

INSERT  INTO @table
        SELECT TOP 1
                id + 1,
                'TEST'
        FROM    @table t1
        WHERE   NOT EXISTS ( SELECT TOP 1
                                    1
                             FROM   @table
                             WHERE  id = t1.id + 1 )
        ORDER BY id

SELECT  *
FROM    @table

结果

id  val
1   Test
2   Test
5   Test 2
24  Test 3
67  Test 4
3   TEST
4   TEST
于 2012-06-25T18:58:34.200 回答
2

我不会那样做的。

正如其他人在评论中已经解释的那样,通过重新填补数字中的空白,您将一无所获。

另外,如果您在其他任何地方引用这些 ID,您甚至可能会无意中弄乱您的数据:
假设曾经有一行ID 2并且您将其删除。
然后插入一个完整的新行并重新使用ID 2.
现在,如果您有任何引用的数据ID 2,它会突然链接到新值而不是旧值。

(挑剔者请注意:是的,如果正确设置了参照完整性,则不应发生这种情况。但并非所有地方都如此,所以谁知道...)

于 2012-06-25T19:01:37.900 回答
1

我删除了关于身份的答案,因为他们没有参与。看看你是否将它用作聚集索引键会很有趣,因为填补空白会违反严格递增值的经验法则。

使用自连接来填补空白相对简单,并且由于您有一个主键,因此该查询应该快速运行以找到第一个空白(当然,您如何处理同时插入和锁定?):

SELECT lhs.ID + 1 AS firstgap
FROM tablename AS lhs
LEFT JOIN tablename AS rhs
    ON rhs.ID = lhs.ID + 1
WHERE rhs.ID IS NULL

并且插入批量记录需要单独完成每个插入,而 IDENTITY 可以为您处理......

于 2012-06-25T18:53:06.277 回答
-2

如前所述:不要担心未使用的 ID。

然而,当发生大量删除时,优化表是一种很好的做法。

在 MySQL 中,您可以这样做:

optimize table tablename
于 2012-06-25T18:44:28.233 回答