我有一个 PK 增长相当快的表,但是由于行被相当一致地删除,它很快就变成了一个非常稀疏的表:
ID VALUE
----------------
1 'Test'
5 'Test 2'
24 'Test 3'
67 'Test 4'
有没有一种方法可以自动在缺少的 ID 中插入下一个值,这样我就不会将该 ID 变得非常大?例如,我想插入 ID 为 2 的“测试 5”。
我有一个 PK 增长相当快的表,但是由于行被相当一致地删除,它很快就变成了一个非常稀疏的表:
ID VALUE
----------------
1 'Test'
5 'Test 2'
24 'Test 3'
67 'Test 4'
有没有一种方法可以自动在缺少的 ID 中插入下一个值,这样我就不会将该 ID 变得非常大?例如,我想插入 ID 为 2 的“测试 5”。
我不是建议做你想做的事,但如果你想这样做,这就是方法。我只是在回答问题,而不是解决问题。
在你的过程中,你会在这样做的时候锁定你的桌子,这样你就不会偷偷溜进来。通过使用链接这个:
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
我不会那样做的。
正如其他人在评论中已经解释的那样,通过重新填补数字中的空白,您将一无所获。
另外,如果您在其他任何地方引用这些 ID,您甚至可能会无意中弄乱您的数据:
假设曾经有一行ID 2
并且您将其删除。
然后插入一个完整的新行并重新使用ID 2
.
现在,如果您有任何引用的数据ID 2
,它会突然链接到新值而不是旧值。
(挑剔者请注意:是的,如果正确设置了参照完整性,则不应发生这种情况。但并非所有地方都如此,所以谁知道...)
我删除了关于身份的答案,因为他们没有参与。看看你是否将它用作聚集索引键会很有趣,因为填补空白会违反严格递增值的经验法则。
使用自连接来填补空白相对简单,并且由于您有一个主键,因此该查询应该快速运行以找到第一个空白(当然,您如何处理同时插入和锁定?):
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 可以为您处理......
如前所述:不要担心未使用的 ID。
然而,当发生大量删除时,优化表是一种很好的做法。
在 MySQL 中,您可以这样做:
optimize table tablename