2015-06-30 50 views
-1

我有一个表,其中有一个主键ID列,并设置为每个新条目增加1,一个相当标准的配置。该表定期用新记录进行更新,每月一次归档到归档表,然后截断。SQL Server标识列重编号

在正常操作下,截断后进入表的下一条记录将是下一个ID值的任何值,确保归档表和“实时”表之间的ID没有重叠。

由于未知因素,活动表中的ID列以某种方式“恢复”回到已经使用的ID。由于这个数据库设计不佳,现在我遇到了一些数据完整性问题。

我的解决方案是更新“活”表中所有记录的ID列,以便与“存档”表中存在的ID无重叠。一旦我更新了ID,我将重新填写标识列,以便将来的记录也不会重叠。

我的问题不在于重新填充列(使用DBCC - 我知道如何做到这一点),而是关于如何使用新的ID值重新编号现有记录。我应该使用循环动态SQL查询(删除记录,插入记录)来做到这一点,还是有一些SQL Server的功能,我不知道可以自动重新编号ID列?

+1

不知道为什么你需要循环或动态SQL。 'BEGIN TRANSACTION; DECLARE @i INT; SELECT @i = MAX(id)FROM dbo.table WITH(HOLDLOCK); INSERT dbo.table(othercols)SELECT othercols FROM dbo.table; DELETE dbo.table WHERE id <= @i; COMMIT TRANSACTION;' –

+0

这是我寻找的答案类型,谢谢!我知道它不一定需要dyn SQL,只是想不出一个聪明的做法。如果你把这个答案放在答案中而不是评论中,我会将它标记为“已接受”。 – LegendaryDude

回答

1

这看起来是这个问题的一个副本 - How to update Identity Column in SQL Server?

谈话的结果上存在,它是可以做到这一点,但不建议 - 尤其是如果有引用此标识符的任何其他表在外键等中的值。如你在问题中提到的,更好地循环并使用光标或类似的方法重新创建记录。

+0

如果它是重复的,那么*标志*作为重复。 – LittleBobbyTables

+0

我不能这样做,因为该功能仅适用于代表性较高的用户。我能回应的唯一方法就是发表一个答案。 http://meta.stackexchange.com/questions/217242/why-dont-i-see-the-option-to-mark-a-question-as-a-duplicate –

+0

唉,我从来没有意识到旗帜(在15声望)不同于标记为重复(在50声望时)。我很抱歉! – LittleBobbyTables

0

只需使用CTE进行简单更新即可。如果你想让ID在某个地方开始,那就是注释中的偏移量。

with myCTE as (
select row_number() over (order by auditDate) + 0 rn/*This is whatever you want the ID's to start at*/, * from testTable 
) 
update myCTE set id= rn; 

这里的SQL小提琴(我用一个非常简单的表格从另一个例子,我有,但它应该很容易看到发生了什么事情)

http://sqlfiddle.com/#!3/ef0b36/1

+0

为什么在更新之前将dbsize设置为0?浪费写入。你不能在sqlserver 2005 –

+0

中使用公用表表达式,这是不好的测试表名称。我已经在我的答案中更新了它(sql小提琴保持不变)。我将所有的ID设置为0. –

+0

@ t-clausen.dk也许你在想2000? CTE在SQL Server 2005中工作正常。 –