【问题标题】:Reuse identity value after deleting rows删除行后重用标识值
【发布时间】:2011-05-16 08:14:22
【问题描述】:

在 SQL Server 2008 Express 中删除行后是否可以重用标识字段值?这是一个例子。假设我有一个以 Id 字段作为主键(身份)的表。如果我添加五行,我将有这 5 个 Id:1、2、3、4、5。如果我要删除这些行,然后再添加五行,新行将有 Id:6、7、8, 9, 10. 可以让它从 1 重新开始吗?

我是否必须从另一个表中删除数据才能完成此操作?感谢您的帮助。

【问题讨论】:

  • 你的意思是身份字段吗?几乎我所有表的主键都是 ID,它通常(尽管不是唯一)是一个身份字段
  • 是的,我的意思是一个身份字段。
  • 有办法做到这一点并不意味着你应该这样做。

标签: sql sql-server tsql sql-server-2008 identity


【解决方案1】:

您可以使用以下设置 IDENTITY 值:

DBCC CHECKIDENT (orders, RESEED, 999)

这意味着您必须根据每个 DELETE 运行语句。这应该开始强调为什么这是一个坏主意......

数据库不关心顺序值 - 仅用于演示。

【讨论】:

  • 如果要插入 ID 为 10 的行,则应重新设置 ID 9。假设增量为 1。
  • 你也可以使用它来找出你当前的种子值:select ident_current('table_name') as current_identity
【解决方案2】:

如果您想在删除所有行后重置身份,请执行以下操作之一

--instead of delete, resets identity value
TRUNCATE TABLE orders

--or if TRUNCATE fails because of FKs, use this after DELETE
DBCC CHECKIDENT (orders, RESEED, 1)

否则,内部值是否与差距无关。

【讨论】:

    【解决方案3】:

    identity 字段默认不重用旧值。您可以使用dbcc checkident 重新设置它们的种子,但不建议这样做,因为如果您重新设置种子低于表中仍然存在的值,您将获得密钥违规。一般来说,你不应该关心 PK 值是什么。它们不连续的事实并没有伤害任何东西。

    【讨论】:

    • 它们不连续的事实确实会伤害一些东西,因为删除的值不会被重用。由于 32 位标识列将被限制为最多 2^32(如果不包括负值,则为 2^31)插入和删除,之后插入会导致溢出错误。它本质上是一种资源泄漏。我做了一些计算,并确定 32 位标识列不是面向未来的,即使是 64 位列也可能不够,因为仅比我的台式机快 1000 倍左右的计算机可以吃掉其中的值不到一年。所以 128 位 GUID FTW。
    • 使用 bigint 作为标识列可以获得 2^63 - 1 行。那是 9 quintillion 行。即使每天插入一万亿次,这仍将持续 25,000 年。
    猜你喜欢
    • 1970-01-01
    • 2011-12-14
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-07
    • 1970-01-01
    • 2015-01-02
    相关资源
    最近更新 更多