【问题标题】:Reuse the deleted row's identity value重用已删除行的标识值
【发布时间】:2018-05-17 06:02:53
【问题描述】:

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

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

【问题讨论】:

  • 为什么要这个要求?
  • 只是好奇。我是编程初学者。
  • 身份列应被视为恰好适合数字列的不透明 blob。系统保证使它们独一无二。只要这就是你使用它们的全部,你会没事的。一旦你开始关心实际数值,你就会开始出错。
  • 别这样。你正在让自己承受巨大的伤害。
  • 有可能但毫无意义。正如 Damien 所写 - 标识列(实际上是每个代理键)不应该具有业务意义值。它们的唯一目的是提供易于使用的行标识符。请注意,它们也应该替换自然键 - 当使用标识列作为表的主键时,您还必须在组成的列(或列)上提供唯一索引(或约束)你的天然钥匙。

标签: sql sql-server


【解决方案1】:

在 SQL Server 2008 Express 中删除行后是否可以重用标识字段值?

是的,但这是您可能做出的最糟糕的决定之一

这太糟糕了,我不会解释怎么做,而是解释为什么这很糟糕。

我们使用标识列来生成与表中包含的数据无关的值。

  • 如果我们使用身份作为主键并重复使用它们的值,那么同一个键将在整个时间内保存 2 个(或更多)不同的实体,特别是在生成报告或拥有其他使用此键但不使用此键的表时会造成混淆没有参照完整性。
  • 当行数增加时,用于识别未使用值(臭名昭著的间隙和孤岛问题)的解决方案非常缓慢。随着行的堆积,这会导致性能下降。
  • 每次在表中插入行时,您都必须应用这种“未使用的数字”逻辑,因此在维护任务中要记住另一件事。
  • 重复使用这些数字几乎没有好处,因为 INTBIGINT 最大值足以支持大多数业务数据。
  • 通常将身份用作主键或与聚集索引一起使用,因为新记录将插入到末尾,从而减少碎片。一旦记录被删除,它会在页面(瑞士奶酪页面)之间产生间隙,这可以通过重建索引来解决。问题出现在重建之后,您可能会在其中大量插入新记录并导致大量页面拆分,从而不必要地影响性能。

当您实际上需要填充标识列中的空白时,我无法想到一个真实的案例,因为此值的目的是与表所代表的实体无关。

【讨论】:

  • 代理标识列,否(它们相当于内存地址)。很少需要确保自然密钥是无间隙的(发票就是其中之一),但在这种情况下,密钥重用会更糟。
【解决方案2】:

如果您要删除表中的所有数据,您可以使用TRUNCATE TABLE,这将帮助您删除表中的全部数据并将标识重置为从 SEED 值开始。

TRUNCATE TABLE MyTable

您也可以使用DBCC CHECKIDENT 将您的身份重新设定为特定值。

DBCC CHECKIDENT ('dbo.MyTable', RESEED, 1);

以下代码将重新识别身份以从 1 开始。

最后,如果您需要填补空白,您需要知道,使用 IDENTITY 您无法填补空白,您需要实现自定义函数以表现得像 IDENTITY 并填补空白。

【讨论】:

  • “你需要实现你的自定义函数来表现得像 IDENTITY 并弥补差距。”这可能是你能给出的最糟糕的建议。尝试创建自己的自动增量机制必然会失败,尤其是在多线程或多用户环境中。
  • 您可以使用 SEQUENCE 来实现该功能,这将帮助您编写上述功能
  • 仅在2012版本或更高版本中,但这也不能解决差距问题。事实上,我怀疑生成标识值的同一机制也负责生成序列(尽管 SQL Server 不是开源的,所以我无法知道)。
【解决方案3】:

如果您从ID 中删除Autoincrement 属性,则可能。

您可以检查表是否为空,并相应地检查INSERT 的值。

【讨论】:

  • 这意味着您现在必须构建代码来为您执行此检查。每次执行 INSERT 时,该代码首先必须检查数字链是否完整,或者填充第一个“空”间隙。性能方面,你会很快受到伤害。简单地让标识列确定下一个值要容易得多。毕竟,id 字段不应该用于包含业务逻辑,而是它们提供了一个简单的入口点来唯一标识一行。
  • @SchmitzIT 显然它的性能很差。要么您必须这样做,要么您必须跟踪另一个表中表的条件(空或最后一个值已被删除),或者您必须获取您正在插入的 ID 的前一个值.无论你做什么,都会像自动增量属性一样流畅。这个问题本身在应用方面缺乏价值,但要学习可以尝试几种技术。
  • 当然。但是,考虑到 OP 的第一条评论“我是编程初学者”,我想指出为什么每个人都认为这是一个坏主意。我同意这可能是一个有趣的挑战,只是为了编写代码,但对于初学者来说,不是。
【解决方案4】:

我们可以通过两种方式做到这一点。

如果是Non Pk Column,插入相同标识号的记录,然后删除之前的标识列值。

如果您不需要 owl 数据,请删除该表并重新创建该表或截断该表并使用 DBCC CHECKIDENT 将您的身份重新设置为特定值。

【讨论】:

    猜你喜欢
    • 2011-05-16
    • 2015-01-16
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 2013-03-05
    • 2015-01-02
    • 2020-08-06
    • 1970-01-01
    相关资源
    最近更新 更多