【问题标题】:Reset Identity column in SQL Server在 SQL Server 中重置标识列
【发布时间】:2010-10-14 09:05:10
【问题描述】:

我正在制作一个存储联系人的 SQL 数据库。我希望能够删除联系人,每个联系人的正确 id 对我的软件连接到它至关重要。可以说我联系了詹姆斯,他是第一个。他的id是0。我加了Mary,她的id是1。如果我删除James,Mary的id怎么设置为0而不是保持1呢?它必须重置,因为她现在是第一个。换句话说,当某人被删除时,如何重置数据库中的所有 ID?谢谢

【问题讨论】:

  • 您究竟为什么要这样做?如果您需要按进入顺序保留它们,您可以设置日期时间戳或添加列以保持排名。
  • 支持这个问题。虽然我同意 OP 试图做的事情是不明智的,但这个问题对于新手程序员来说是一个很好的路标,说明什么不该做什么以及为什么。得到很多赞成的答案似乎很好地解决了这个问题并且很有启发性。
  • 对于初学者来说这是一个典型的错误。感觉他们的 ID 会用完,他们想放慢增长速度。
  • 一个常规整数只有 2,187,000,000 或类似的空间。因此,它很容易用完并且需要重新组织 id。
  • @djangofan:你用完了多少次? ....

标签: sql-server database-design identity


【解决方案1】:

这在很多方面都是一个坏主意。我正在争论是否应该向您展示如何做到这一点。一旦设置了行的标识,就不应该有理由更改它。

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

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

【讨论】:

    【解决方案2】:

    一旦您在数据库中拥有大量记录,这将变得非常缓慢。标识列对您不起作用,您需要执行一些自定义 T-SQL 来不断更改所有数字 - 但这是一个非常糟糕的主意,IMO。

    如果您需要跟踪它们的添加顺序,为什么不使用日期/时间戳?

    您需要重新考虑您的设计。

    【讨论】:

      【解决方案3】:

      这不是 ID 的工作方式,也不是它们应该如何工作的方式。 ID 不应更改,否则所有链接信息将指向错误的行。

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

      【讨论】:

        【解决方案4】:

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

        如果您确实必须有某种形式的线性标识符,它总是从 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 由于记录被删除而“缺失”值,那么软件应该测试这些值是否存在,而不是只是假装出来。

        【讨论】:

          【解决方案5】:

          ID 是行的唯一标识符

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

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

          【讨论】:

            【解决方案6】:

            与每次删除行时重新编号标识列相比,使用另一种方法会更好地解决此问题。

            如果不知道您的应用程序为何需要此功能,很难确切地说您还会做什么,但您的应用程序需要此功能这一事实可能表明某处存在设计问题。

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                【解决方案8】:

                1 分钟的谷歌搜索给了我一个我无法显示的页面。谷歌这个,它会是你在 2009 年 6 月 1 日的第一个链接:tsql fix "identity column"

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

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

                声明@MaxID INT

                从 TableID 中选择 @MaxID = COUNT(ID)

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

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

                很复杂吧?这就是为什么最好从右脚开始。 ;)(我从经验中学到了这一点)如果您还有任何问题,请通过 maraarone et yahoo d0t com 给我发电子邮件。

                【讨论】:

                  【解决方案9】:

                  我编写了一个应用程序来处理多层次的销售程序。 当然,人们会退出。在我们的系统中,也必须插入人员。

                  只需一次修改,您就走在了正确的轨道上。

                  标识号 (ID) 和序列号 (seq) 是两个不同的东西。 他们之间根本没有任何关系。

                  切勿更改 ID。一旦分配,永远分配。

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

                  随意调整 cNEXT 中的 ID,重新分配 cNEXT。 任何存储过程都可以做到这一点。

                  然后,您还可以灵活地创建不连续的 ID 链。 当人们搬到不同的地区时,这很有用 或获得晋升到不同的群体。

                  希望这会有所帮助! :)

                  【讨论】:

                    【解决方案10】:

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

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

                    *先使用id从所有表中删除所有行

                    【讨论】:

                      猜你喜欢
                      • 2011-05-27
                      • 1970-01-01
                      • 2011-01-07
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多