【问题标题】:How can I replace the existing primary key with a new primary key on my table?如何用表上的新主键替换现有主键?
【发布时间】:2011-10-17 22:30:38
【问题描述】:

我正在使用旧版 SQL Server 数据库,该数据库的核心表带有错误的主键。

键的类型为NVARCHAR(50),包含应用程序根据表中的各种内容生成的字符串。出于显而易见的原因,我想将此键替换为自动递增(身份)INT 列。

这是一个巨大的数据库,我们正在逐步升级它。我们希望最小化对其他组件写入的表的更改。我想我可以改变桌子而不会破坏任何东西:

  1. 将新的 Id 列添加到表中并使其可以为空
  2. 用唯一的整数填充它并使其成为NOT NULL
  3. 删除现有主键,同时确保该列上仍有唯一性约束
  4. 将新的 Id 列设置为新的主键和标识

事实证明,第 3 项非常痛苦。因为这是一个核心表,所以有 lot 其他表具有外键约束。要删除现有的主键,我似乎必须删除所有这些外键约束并在之后再次创建它们。

有没有更简单的方法可以做到这一点,还是我只需要编写所有脚本?

【问题讨论】:

  • 快速问题: 1. 当您说删除此主键时,您并不是说删除列,对吗? 2. 您是否尝试禁用其他表上的外键约束:ALTER TABLE NOCHECK CONSTRAINT 。这可能会帮助您完成第 4 点,并在完成后重新启用 fk 约束
  • 1.正确 - 我实际上想保持所有外键约束不变。我没有尝试禁用它们,但错误表明我需要实际删除它们。不过我可以试试吗?
  • 不,我认为您根本不需要删除它们。只需禁用它们,做你的事情并再次重新启用它们。 @ericb 链接的脚本做同样的事情。 ALTER TABLE NOCHECK CONSTRAINT 禁用和 ALTER TABLE CHECK CONSTRAINT 启用
  • 好的,我尝试禁用它们,然后进行更改。不幸的是,当我尝试删除主键时它就失败了。但 drop 和 recreate 方法有效。

标签: sql sql-server database-design database-schema


【解决方案1】:

我曾经做过同样的事情,并且基本上使用了您描述的过程。当然除了你必须首先访问其他表并添加指向基表中新列的新外键

所以我使用的方法是

  1. 在基表中添加一个具有自动递增整数的新列,确保其上有唯一索引(稍后将由主键替换)
  2. 为每个指向基表的外键关系在子表中添加一个新列。 (请注意,如果有多个关系,这可能会导致在子表中添加多个列)
  3. 对于子表中的每个键实例,在新的外键字段中输入一个值
  4. 替换您的外键关系,以便新列现在提供服务
  5. 将基表中的新列设为主列
  6. 删除基表中的旧主键和每个旧外键 孩子们。

这是可行的,并不像一开始听起来那么难。症结在于自然的children表的一系列更新语句

Update child_table
set new_column = (select new_primary from base)
where old_primary = old_foreign

【讨论】:

  • 是的,我喜欢这种策略。不幸的是,因为我们一次只做一点点,我不想更改这些外键引用。目前,我可以让他们指着旧钥匙。当我们更新这些表时,我们将跨越那座桥。
  • 我遇到了同样的问题。我仍然先构建外键。第 6 项发生需要几个月的时间,但这意味着需要一段时间来维护两组密钥。您仍然必须能够添加新的外键关系并让它们工作。我确实认为更快更好。用 2-3 张桌子证明概念,然后再努力。
【解决方案2】:

恐怕这是个坏消息。我们刚刚完成了一个做同样类型事情的大项目,尽管我们的首席 DBA 有一些技巧。您可能会查看 this 之类的内容来生成用于翻转开关的脚本:

【讨论】:

  • 谢谢。这就是我最终使用的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
  • 2014-05-05
  • 2014-07-03
  • 2015-07-01
相关资源
最近更新 更多