SQL Server标识列重新编号[重复]

Posted

技术标签:

【中文标题】SQL Server标识列重新编号[重复]【英文标题】:SQL Server Identity Column Renumbering [duplicate] 【发布时间】:2015-06-30 20:17:50 【问题描述】:

我有一个表,它有一个主键 ID 列,并设置为每个新条目递增 1,这是一个相当标准的配置。该表会定期用新记录更新,并每月存档一次到存档表,然后截断。

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

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

我解决此问题的解决方案是更新“实时”表中所有记录的 ID 列,这样就不会与“存档”表中存在的 ID 重叠。更新 ID 后,我将重新设置 Identity 列,这样以后的记录也不会重叠。

我的问题不是重新播种列(使用 DBCC -- 我知道如何做到这一点),而是关于如何使用新的 ID 值重新编号现有记录。我应该使用循环的动态 SQL 查询(删除记录、插入记录)来执行此操作,还是有一些我不知道的 SQL Server 函数可以自动重新编号 ID 列?

【问题讨论】:

不知道为什么需要循环或动态 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; 这是我正在寻找的答案类型,谢谢!我知道它不一定需要 dyn SQL,只是想不出一种聪明的方法来做到这一点。如果您将其放在答案而不是评论中,我会将其标记为“已接受”。 【参考方案1】:

这看起来是这个问题的重复 - How to update Identity Column in SQL Server?

那里的对话的结果是可以这样做,但不建议这样做 - 特别是如果有任何其他表在外键等中引用此标识符值。最好使用循环遍历并重新创建记录如您在问题中提到的那样,光标或类似名称。

【讨论】:

如果是重复的,则标记为重复。 我不能,因为该功能仅适用于具有较高代表的用户。我能回应的唯一方法是发布答案。 meta.stackexchange.com/questions/217242/… 嗯,我从来没有意识到标记(15 声望)与标记为重复(50 声望)不同。抱歉! 不用担心。这是一个非常愚蠢的规则。【参考方案2】:

只需使用 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

【讨论】:

为什么在更新之前将 dbsize 设置为 0?浪费写。您不能在 sqlserver 2005 中使用公用表表达式 这是错误的测试表名称。我已经在我的答案中更新了它(虽然 sql fiddle 保持不变)。我将所有 ID 设置为 0。 @t-clausen.dk 也许你在想 2000 年? CTE 在 SQL Server 2005 中运行良好。 不仅浪费写入,而且你不能这样做 (Msg 8102, Level 16, State 1 / Cannot update identity column 'id'.) IDENTITY_INSERT 会开启身份insert,而不是身份update

以上是关于SQL Server标识列重新编号[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 中重新设置标识列?

SQL Server中的标识列

使用sql语句创建修改SQL Server标识列(即自动增长列)

使用sql语句创建修改SQL Server标识列(即自动增长列)

如何在 SQL Server 中添加标识列?

SQL Server - 重置标识字段[重复]