我有一个问题我正在使用现有的SQL Server 2008数据库:我需要偶尔更改表中某些现有记录的主键值。不幸的是,大约有30个其他表具有对该表的外键引用。
更改主键和相关外键的最佳方式是什么?
我不是在可以更改现有密钥结构的情况,因此这不是一个选项。此外,随着系统的扩展,更多表将与此表相关,因此可维护性非常重要。我正在寻找最优雅和可维护的解决方案,非常感谢任何帮助。到目前为止,我一直在考虑使用存储过程或触发器,但在向错误的方向前我想要一些建议。
谢谢!
答案 0 :(得分:7)
当您说“我不在可以更改现有密钥结构的情况下”时,您是否可以将ON UPDATE CASCADE选项添加到外键?这是处理这种情况的最简单方法 - 无需编程。
答案 1 :(得分:2)
正如Larry所说,On Update Cascade可以工作,但是,它可能会导致生产数据库出现重大问题,大多数dbas都不会因为让你使用它而兴奋不已。例如,假设您有一个客户更改了他的公司名称(即PK),并且各种表中有两百万条相关记录。在更新时,Cascade将在一个事务中执行所有更新,这可能会锁定主表几个小时。这就是为什么要有一个需要改变的PK是一个非常糟糕的主意。触发器也同样糟糕,如果写错了,可能会更糟糕。
如果你在存储过程中进行更改,你可以将每个部分放在一个单独的事务中,所以至少你没有锁定所有内容。您还可以批量更新记录,这样,如果您要在表中更新一百万条记录,您可以在较小的批次中执行这些记录,这些记录将运行得更快并且锁定更少。执行此操作的最佳方法是使用新PK在主表中创建新记录,然后批量将旧记录移动到新记录,然后在移动所有相关记录后删除旧记录。如果您执行此类操作,最好使用审计表,以便在出现问题时可以轻松还原数据,因为您希望在多个事务中执行此操作以避免锁定整个数据库。现在这很难维护,你必须记住在添加FK时添加到proc(但是你必须记住在UPDATE CASCADE上做)。另一方面,如果它由于新FK的问题而中断,这是一个简单的修复,你知道问题是什么,并且可以很容易地相对快速地改变产品。
这个问题没有简单的解决方案,因为基本问题是设计不佳。您将不得不查看所有解决方案的优缺点(我会抛出触发器的想法,因为Cascade Update将表现更好并且更少受到错误的影响)并确定哪种解决方案最适合您的情况。请记住,数据完整性和性能对于企业数据库至关重要,并且可能比可维护性更重要(异端,我知道)。
答案 2 :(得分:1)
如果您必须定期更新主键,那么就出现了问题。 :)
我认为最简单的方法是添加另一列并将其作为主键。这将允许您轻松更改值并且还与外键相关。此外,我不明白为什么你不能改变现有的密钥结构。
但是,正如你在问题中指出的那样(和Larry Lustig评论)你无法改变现有的结构。但是,我担心如果它是一个需要频繁更新的列,那么使用触发器可能会对性能产生负面影响。并且,您还说,随着系统的扩展,更多的表将与此表相关,因此可维护性非常重要。但是,现在快速修复只会使问题恶化。