Sql server 在不删除截断表的情况下重置主键

Sql server 在不删除截断表的情况下重置主键,sql-server,sql-server-2012,primary-key,Sql Server,Sql Server 2012,Primary Key,我有一个带有主键的表,现在没有任何理由我不知道何时插入数据,它是这样加载的 Pk_Col Some_Other_Col 1 A 2 B 3 C 1002 D 1003 E 1901 F 是否有任何方法可以在不删除/截断表格的情况下按如下方式重置表格 Pk_Col Some_Other_Col 1 A 2 B 3 C 4

我有一个带有主键的表,现在没有任何理由我不知道何时插入数据,它是这样加载的

Pk_Col Some_Other_Col
1           A
2           B
3           C
1002        D
1003        E
1901        F
是否有任何方法可以在不删除/截断表格的情况下按如下方式重置表格

Pk_Col Some_Other_Col
1           A
2           B
3           C
4           D
5           E
6           F
试试这个。

如果你真的想拥有整洁的标识值,你可以编写一个游标(速度慢但可维护),或者调查任何数量的“我如何在序列中找到差距”问题,并相应地执行一个
更新
(运行速度更快,但要正确操作很困难)。当外键指向此表时,这将变得非常困难。随时准备在将数据放入此表或从此表中删除数据时重新运行此脚本

编辑
标识
列本身无法更新。但是,您可以设置IDENTITY\u INSERT dbo.MyTable ON,
插入一行,其中包含所需的
标识
值和现有行其他列中的值,然后
删除现有行。对数据的净影响与
更新相同

这样做的唯一合理原因是,如果表中有大约20亿行,并且标识列的整数即将用完。如果是这样的话,你还需要担心一大堆其他的事情


但是说真的-听@Damien的,别担心。

你不能更新身份栏,所以删除/插入是唯一的方法。您可以重新设置标识列的种子并重新创建数据,如下所示:

DBCC CHECKIDENT ('dbo.tbl',RESEED,0);    
INSERT INTO dbo.tbl (Some_Other_Col)
SELECT Some_Other_Col
FROM (DELETE FROM tbl OUTPUT deleted.*) d;

这假设没有外键引用此数据。

如果您关心标识列的数值(这是您实际询问的内容。主键的概念与标识列的概念正交),则使用它们是错误的。您应该将其视为恰好适合数字列的不透明水滴。您不应该向任何人显示这些值,因此,实际值的赋值应该无关紧要。@ZeroTo确定他所做的点是,如果这是一个标识列,那么这些值是任意的,而与值的大小无关。1,2,3,7有什么区别?如果有差距,差距就会出现,这无关紧要,所以不要担心。我的观点的第一部分是,您真正谈论的是表中的标识列。是的,它可能恰好是这个表的主键,但当您谈论自动编号时,您谈论的是标识列。可能存在标识列和PK列完全不相同的表。@Zerotoinfinite如果您认为
Identity
列的全部要点是它可以是非顺序的。这是因为数据库会在后台自动为您处理并发写入/回滚等事情。这其中的一部分将涉及到在你的序列中有“间隙”。如果您不希望出现差距,请不要使用
标识
,但如果您试图制定自己的解决方案,也要为糟糕的性能和大量问题做好准备。请不要这样做。没有必要,几乎没有理由重新设定键值的种子。如果20亿的整数用完了,那么你就忘记了负数
;-)。将您的身份重新设定为0,步骤为-1。第一段不正确。很遗憾,您无法更新SQL Server中的标识列。如果可以的话,就有了更简单、更有效的方法,不用光标。@gvee-大多数人确实忘记了负片。您是否见过语句
创建表dbo.XYZ(ID int IDENTITY(-2147483648,1)…
?我没有见过。@MichaelGreen我见过!
;-)
比使用
bigint
的常规更改要高效得多。只有在没有选择unsigned的情况下,才使用负数,那么您现在意外地拥有了两倍的空间(比您使用的值)“思想”),但是如果你选择了无符号,你就不能获得更多的负空间,原因有两个,一是无符号,你实际上不能加“-”,第二,这两种方式都是相同的空间,就像“Tinyint”一样,有符号的范围是-128到127。无符号的范围是0到255,你仍然只能有256个插槽。
DBCC CHECKIDENT ('dbo.tbl',RESEED,0);    
INSERT INTO dbo.tbl (Some_Other_Col)
SELECT Some_Other_Col
FROM (DELETE FROM tbl OUTPUT deleted.*) d;