2013-03-25 59 views
0

我对数据库非常陌生,所以请和我一起裸照。添加外键关系是否危险?

作为一名程序员,添加对象的引用是相当安全的,但添加外键关系(我认为)是非常危险的。通过添加FK关系,必须更新从此外部表中删除行的所有查询,以在实际删除行之前正确删除与该行关联的外键。如何搜索从外表中删除行的所有查询?这些查询可以隐藏在代码和存储过程中。这是维护噩梦的真实生活的例子吗?有没有解决这个问题的方法?

+0

我知道如果你尝试删除乱序(例如:在FK之前删除PK),SQL Server实际上会抛出一个错误,但我不确定这是否适用于所有SQL。 – 2013-03-25 18:27:15

+3

在RDBMS中强烈建议定义一个外键。如果要删除父表中的记录,请清除子表中的相关记录,然后清除父表记录。 – 2013-03-25 18:27:19

+0

您认为您了解外键的一切都是错误的。这个问题的答案几乎开始填补你的教育空白。你需要做更多的研究和阅读。 – 2013-03-25 18:34:37

回答

1

你不应该从一开始就设计一个没有外键的关系型数据库。这是一段时间内数据完整性不佳的保证。

您可以添加代码并使用级联删除,如其他人所建议的那样,但这通常也是错误的答案。有时您真的希望删除因为您有子记录而停止。例如,假设你有客户和订单。如果您删除了有订单的客户,那么您将失去订单的财务记录,这是一场灾难。相反,您会希望应用程序发生错误,说明此客户的订单存在。进一步级联删除可能会突然让您删除数百万个子记录,从而在大量事务发生时锁定您的数据库。这是一种危险的做法,应该很少用于生产数据库。

添加FK(如果您有关系,则需要),然后搜索从该表中删除并适当调整的代码。考虑一下软删除不是一个更好的选择。这是您将记录标记为已删除或不活动的位置,因此它不再显示为数据输入选项,但您仍可以看到现有记录。再次,您可能需要相当严格地调整数据库代码才能正确实现。有一个从一开始就设计得很差的数据库并不容易。

如果您认为您将拥有许多子记录并且实际上想删除它们,那么软删除也是一个不错的选择。这样,您可以标记记录,使其不再显示在应用程序中,并使用在非高峰时段运行的作业批量删除记录。

如果您要添加一个新表并添加一个FK,它肯定会比较容易处理,因为您会在编写任何代码之前创建该表。

1

您的陈述根本不正确。建立外键关系时,可以将级联属性设置为cascade delete。一旦完成,子记录将在删除父项时被删除,确保没有记录被孤立。

+0

当然,级联应该很少做,它也是危险的。 – HLGEM 2013-03-25 19:32:25

+0

@HLGEM,我认为你的陈述有点误导。有很多完全可以接受的(和安全的)实例级联删除应该完成。例如,订单和订单明细记录。如果订单被删除(除非您的DBA赞赏孤立记录),则详细记录**必须删除。当然,订单记录可能不应该首先被删除,但这是另一个问题。 – 2013-03-25 19:47:57

+0

当然,子记录应该被删除,它们只是不应该在级联中自动删除,或者如果你有太多的话可以锁定服务器。我不知道很多dbas谁会允许生产数据库使用级联删除。 – HLGEM 2013-03-25 20:41:49

1

如果使用正确的ORM解决方案,正确配置FK和PK,并且启用级联删除,则不应该有任何问题。

1

我不会这么说(以确认其他人提到的是什么) - 这通常是通过级联删除来处理的。提供你想要的那种方式 - 或者用小心谨慎的程序来清理背后的东西。

更大的系统是您可以看到更多'程序',而不是'自动化'(即级联删除)。对于更大的设置 - DBA-s通常更喜欢在数据库维护阶段处理这个问题。通常情况下,通过中间件应用程序代码不允许删除记录 - 但只是将其标记为“已删除”或不活动 - 并根据组织中存在的数据库例程和程序(存档等)进行处理。 。

除非你有一个非常大的代码库,这不是一个大问题。另外,通常,大部分Db代码都会通过一些可以轻松遍历的DAL层。或者你也可以查询所有关系和'依赖关系'的系统表,并且许多例程都是为这样的代码维护而编写的(在'fence'的两侧)。这并不是说这不是一个'问题',只是和普通的Db工作没什么不同 - 而且还有比这更糟糕的事情。

So, I wouldn't lose my sleep over that。围绕使用“太多”参照完整性约束(性能,维护)还存在其他问题 - 但这在DBA-s(以及一般的Db专业人员)中通常是一个非常有争议的问题,所以我不会深入了解:)