简体   繁体   English

添加外键关系危险吗?

[英]Is adding a foreign key relationship dangerous?

As a programmer, adding a reference to an object is pretty safe but adding a foreign key relationship (I think) is pretty dangerous. 作为程序员,添加对对象的引用非常安全,但是添加外键关系(我认为)非常危险。 By adding a FK relationship, ALL the queries that delete a row from this foreign table has to be updated to properly delete the foreign key that's tied to that row before actually deleting the row. 通过添加FK关系,必须更新所有从此外表中删除行的查询,以在实际删除该行之前正确删除与该行绑定的外键。 How do you search for all the queries that delete a row from this foreign table? 您如何搜索从该外部表中删除行的所有查询? These queries can lie buried in code and in stored procedures. 这些查询可以隐藏在代码和存储过程中。 Is this a real life example of a maintenance nightmare? 这是维护噩梦的真实例子吗? Is there a solution to this problem? 有解决这个问题的方法吗?

Your statement is simply not true. 您的说法根本不正确。 When establishing a foreign key relationship, you can set the cascading property to cascade delete . 建立外键关系时,可以将级联属性设置为层叠cascade delete Once that's done, the child records will be deleted when the parent is deleted, ensuring that no records are orphaned. 完成此操作后,删除父记录时,子记录也将被删除,以确保没有孤立的记录。

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

I wouldn't say so (to confirm what others mentioned) - that is usually taken care of with cascading deletes. 我不会这么说(以确认其他人提到的内容)-通常通过级联删除来解决。 Providing you want it that way - or with careful procedures that clean things behind. 只要提供您想要的方式-或使用仔细的程序清理掉后面的东西。

The bigger system is you get to see more of the 'procedures' and less of the 'automation' (ie cascade deletes). 更大的系统是您可以看到更多的“过程”,而更少的“自动化”(即级联删除)。 For larger setups - DBA-s usually prefer to deal with that during database maintenance phase. 对于较大的设置-DBA-s通常更喜欢在数据库维护阶段进行处理。 Quite often, records are not allowed to be deleted, through middle-ware application code - but are simply marked as 'deleted' or inactive - and dealt with later on according to database routines and procedures in place in the organization (archived etc.). 通常,不允许通过中间件应用程序代码删除记录,而只是将其标记为“已删除”或“不活动”,然后根据组织中已有的数据库例程和过程(已归档等)进行处理。 。

And unless you have a very large code base, that's not a huge issue. 而且,除非您的代码库很大,否则这不是一个大问题。 Also, usually, most of the Db code goes through some DAL layer which can be easily traversed. 同样,通常,大多数Db代码都经过一些DAL层,该层很容易遍历。 Or you can also query system tables for all the relationships and 'dependencies' and many routines were written for such a code maintenance (on both sides of the 'fence'). 或者,您也可以查询系统表以获取所有的关系和“依赖关系”,并且为此类代码维护编写了许多例程(在“栅栏”的两侧)。 It's not that it's not an 'issue', just nothing much different than normal Db work - and there're worse things than that. 这并不是说这不是一个“问题”,与正常的Db工作没什么大不同-还有比这更糟糕的事情。

So, I wouldn't lose my sleep over that . So, I wouldn't lose my sleep over that There are other issues with around using 'too much' of the referential integrity constraints (performance, maintenance) - but that is often a very controversial issue among DBA-s (and Db professionals in general), so I won't get into that:) 关于使用过多的参照完整性约束(性能,维护)还有其他问题-但这在DBA(通常是Db专业人员)中通常是一个非常有争议的问题,因此我不会去讨论:)

You should never design a relational database without foreign keys from the very beginning. 从一开始就永远不要设计没有外键的关系数据库。 That is a guarantee of poor data integrity over time. 随着时间的流逝,这保证了不良的数据完整性。

You can add the code and use cascade delete as others have suggested, but that too is often the wrong answer. 您可以添加代码并按照其他人的建议使用级联删除,但这通常也是错误的答案。 There are times when you genuinely want the delete stopped because you have child records. 有时您确实希望删除停止,因为您有子记录。 For instance, suppose you have customers and orders. 例如,假设您有客户和订单。 If you delete a customer who has an order, then you lose the financial record of the order which is a disaster. 如果删除有订单的客户,那么您将丢失订单的财务记录,这是一场灾难。 Instead you would want the application to get an error saying an order exists for this customer. 相反,您希望应用程序收到一条错误消息,指出该客户存在订单。 Further cascade delete could suddenly get you into deleting millions of child records thus locking up your datbase while a huge transaction happens. 进一步的级联删除可能突然使您删除数百万个子记录,从而在发生大量事务时锁定了您的数据库。 It is a dangerous practice that should rarely, if ever, be used in a production database. 这是一种危险的做法,几乎永远不会在生产数据库中使用它。

Add the FK (if you have the relationships, it is needed) and then search for the code that deletes from that table and adjust it appropriately. 添加FK(如果你有关系,需要),然后搜索代码,从该表中删除,并适当调整。 Consider if a soft delete isn't a better option. 考虑软删除是否不是更好的选择。 This is where you mark a record as deleted or inactive, so it no longer shows up as a data entry option, but you can still see the existing records. 这是你标记纪录删除或不活动,所以它不再显示为数据输入选项,但你仍然可以看到现有的记录。 Again you may need to adjust your database code fairly severly to implement this correctly. 同样,您可能需要相当大地调整数据库代码才能正确实现此目的。 There is no easy fix for having a database that was badly designed from the start. 从一开始就设计不好的数据库是没有容易的解决方法的。

The soft delete is also a good choice if you think you will have many child records and actually do want to delete them. 如果您认为自己将有许多子记录并且确实要删除它们,那么软删除也是一个不错的选择。 This way you can mark the records so they no longer show in the application and use a job that runs during non-peak hours to batch delete records. 这样,您就可以标记记录,使其在应用中不再显示和使用的作业,在非高峰时段批量删除记录运行。

If you are adding a new table and adding an FK, it is certainly easier to deal with becasue you would create the table before writing any code against it. 如果要添加新表并添加FK,那肯定是比较容易处理becasue你会写代码对之前创建表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM