从表中插入缺失值

时间:2012-06-25 18:35:17

标签: sql sql-server insert primary-key

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

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

有没有办法可以自动在缺少的ID中插入下一个值,这样我就不会将ID增长到极大?例如,我想插入ID为2的“测试5”。

4 个答案:

答案 0 :(得分: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

<强> RESULT

id  val
1   Test
2   Test
5   Test 2
24  Test 3
67  Test 4
3   TEST
4   TEST

答案 1 :(得分:2)

我不会这样做。

正如评论中其他人已经解释过的那样,通过重新填补数字中的空白,你什么也得不到。

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

(对于挑剔者的注意事项:是的,如果正确设置了参照完整性,就不会发生这种情况。但到处都不是这种情况,所以谁知道......)

答案 2 :(得分: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可以为您处理...

答案 3 :(得分:-2)

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

但是,当发生大量删除时,优化表是一种好习惯。

在MySQL中,你可以这样做:

optimize table tablename