在SQL Server中重置标识列

时间:2009-03-19 17:48:53

标签: sql-server database-design identity

我正在建立一个存储联系人的SQL数据库。我希望能够删除联系人,并且每个联系人的正确ID对于我连接到它的软件至关重要。让我们说我有联系詹姆斯,他是第一个。他的身份证是0.我加上玛丽,她的身份证是1.如果我删除詹姆斯,玛丽的身份证如何设置为0而不是1?它必须重置,因为她现在是第一个。换句话说,当有人被删除时,如何重置数据库中的所有ID?感谢

10 个答案:

答案 0 :(得分:16)

这在很多方面都是个坏主意。我正在辩论是否应该告诉你如何做到这一点。一旦设置了行的标识,就永远不应该有理由改变它的标识。

如果您可能使用了错误的字段作为PK标识符。我在这里假设您正在谈论您的PK字段,这也是一个标识列。

请记住,如果您创建链接到联系人表的任何表,并且您开始更改您的ID,则还需要更新所有这些表。这将变得昂贵......

答案 1 :(得分:6)

一旦你在数据库中拥有超过一小部分记录,那就会变得非常缓慢。标识列不适合你,你需要做一些自定义的tsql来改变所有的数字 - 但是一个非常糟糕的主意,imo。

如果您需要跟踪添加的订单,为什么不使用日期/时间戳。

你需要重新思考你的设计。

答案 2 :(得分:5)

这不是ID如何工作,而不是它们应该如何工作。 ID永远不会改变,或者所有链接的信息都指向错误的行。

相反,为什么不添加您控制的“External_ID”列?或者在查询中动态编号(使用计算列?)

答案 3 :(得分:4)

ID是行的唯一标识符

它可用于将行链接到另一个表中的另一行。 ID的缺失本身也包含信息,因为它会清楚地表明它已被删除。开始回收ID号完全打败了拥有唯一标识符的目的,并且没有任何意义。将ID分配给某行后,您不能随意更改它。

想象一下,当有人去世时,他们将社会保险号码(ID)交给其他人。这将导致将与死者的社会保险号码相关联的所有旧信息转移给该新人,这没有任何意义。 ID也是如此,如果重新分配了ID,它将继承以前链接到它的任何旧数据。

答案 4 :(得分:3)

使用另一种方法比使用每次删除行时重新编号标识列更好。

如果不知道你的应用程序为什么会有这种需要,很难确切地说你会做什么,但是你的应用程序需要这个功能的事实可能表明某个地方存在设计问题。

答案 5 :(得分:3)

在自动递增的主键列上执行此操作是没有意义的,因为即使这样做很简单,在相关表中没有大量更新也会影响数据完整性。为此,您可能需要从列中删除索引和主键约束(此时应用程序可能会剥落),重新编号所有后续记录,重新编号所有相关表,然后重新应用主键约束和索引。

如果你真的必须有某种形式的线性标识符,它总是从0开始(这可能表明软件设计有问题)那么除了主键之外你还可以有一个辅助ID列,然后你可以更新到使用以下语句将更高的值拖放到梯级中:

UPDATE table
SET secondaryID = secondaryID - 1
WHERE secondaryID > (SELECT secondaryID FROM table WHERE primaryID = [id to delete]);

DELETE FROM table
WHERE primaryID = [id to delete];

我强烈反对这种做法 - 如果由于删除记录而导致您的ID“缺失”,则软件应测试这些值是否存在,而不是仅仅是躲避。

答案 6 :(得分:2)

您使用的ID不仅仅是标识符。如果是这种情况,您将无法使用自动增量字段。您需要在代码中处理此问题。

答案 7 :(得分:1)

1分钟的谷歌搜索给了我一个我无法显示的页面。谷歌这个,它将是你在2009年6月1日的第一个链接:tsql修复“标识栏”

基本上,我会建议在进行任何重新编号之前在所有关系字段之间添加一个外键约束(如果有任何关系,这也是一个可怕的想法,严格来说,因为如果你问这个问题,你会有一段时间)。

如果您的联系人表是您的唯一表或基于此ID字段具有ZERO关系,您可以将Identity属性设置为NO,将值重新编号为1到COUNT(ID),然后将Identity属性设置为YES,并且使用以下方法重新标记完成身份:

DECLARE @MaxID INT

SELECT @MaxID = COUNT(ID)FROM TableID

DBCC CHECKIDENT('TableID',RESEED,@ MaxID)

在这种情况下,您可以在每组删除后使用上面的重新设定脚本(但是一旦最初并正确设置了所有内容,将COUNT(ID)更改为MAX(ID),这会随着表变大而增加一点速度),在任何其他插入或外键约束更新之前。确保使用包含删除和重新播种块的TRANSACTIONS,并确保该表仅允许同步事务,这将防止在重新设置过程中的任何数据冲洗。

复杂的呃?这就是为什么最好从右脚开始。 ;)(我从经验中学到了这一点)如果您还有其他问题,请发送电子邮件至mraarone et yahoo d0t com。

答案 8 :(得分:0)

我写了一个处理多层次销售计划的应用程序。 当然,人们退学了。在我们看来,人们也必须插入。

你在正确的轨道上进行了一次修改。

身份证号码(ID)和序列号(seq)是两回事。 他们根本没有任何关系。

永远不要更改ID。分配后,始终分配。

在表格中为序列创建一个列(cNEXT)并使用ID填充它。 “这个序列中的下一个是什么ID?”

随身携带cNEXT中的ID,随时重新分配cNEXT。 任何存储过程都可以做到。

然后,您还可以灵活地创建非顺序ID链。 当人们搬到不同的地区时,这很有用 或者获得不同团体的促销活动。

希望这有帮助! :)

答案 9 :(得分:0)

所有答案都假设这是一个生产环境。如果你测试数据库设计,那么想要快速截断所有表,应该有一个简单的方法来实现这个:

DBCC CHECKIDENT({table name},reseed,0)

*使用id first

删除所有表中的所有行