这不是一个特定的问题,更多的是一般的疑惑。
当你必须以1:M的关系对多个表进行删除时,最好是通过级联删除制作FK约束还是加入delete语句中的表。
我有一个旧项目,它对相关表有单独的删除语句,有些语句没有被执行,数据完整性也被破坏了。我不得不在两者之间作出决定,所以我想了一下什么是更好的解决方案。
还可以选择制作存储过程或事务。
所以我正在寻找意见或建议......?
答案 0 :(得分:7)
我认为使用级联删除更安全。如果您决定使用连接,则必须记住每次从父表中删除任何内容时都使用它们;即使你有足够的纪律来做到这一点,你也无法确定你的同事或将来会支持你的软件的人。此外,不止一次地编码关于表关系的这种知识违反了DRY原则。
如果您使用级联删除,则无需记住任何内容,并且将始终根据需要删除子行。
答案 1 :(得分:4)
级联删除会导致很多问题,因此非常危险。我不建议使用它。首先,假设我需要删除具有数百万个子记录的记录。您可以锁定数据库并使其无法使用数小时。我知道很少有dbas允许在他们的数据库中使用级联删除。
接下来,如果您定义了FK,它对数据完整性没有帮助。具有子记录的删除仍然存在将失败,这是良好事物。如果他有现有订单,我希望客户删除失败。不经意地使用级联删除(通常是根据我的经验)可以导致删除您真正不想删除的内容。
答案 2 :(得分:4)
如果您的数据库具有为其定义的正确RI,则不应存在任何数据完整性受损的情况。您的所有相关表都应具有声明性RI,这意味着无法删除父级仍然有子级的父级。
此外,如果您的代码有时只删除某些行,那么编码很差,测试也很差。这些行为应该是单一交易。您对使用存储过程的建议是解决该问题的一种很好的方法,并且非常标准。
正如已经提到的,级联触发器存在删除某人不打算删除的行的危险。考虑到有时人们可能会从应用程序之外的某个位置访问您的数据,尤其是在修复数据问题时。当有人意外地尝试删除错误的父级并获得一个好的RI错误。当他们意外地尝试删除错误的父母时,它不仅删除了那个父母而且还删除了其他5个桌子中的20个孩子,这是不好的。
此外,级联删除非常隐蔽。如果开发人员正在编写父母的删除,那么他们应该知道他们必须使用删除存储过程来照顾孩子。最好让开发人员不反对该代码,获取错误并修复他的代码(或者意识到他并不是真的想要完成所有这些删除),而不是让开发人员抛出删除并拥有在代码上线之前,没有人意识到这会杀死孩子。
IMO,我更倾向于让我的开发人员了解应用程序,而不是让他们更容易对此保持无知。
答案 3 :(得分:0)
同时使用!
“已加入”手动删除通常可以更好地避免死锁和其他争用问题,因为您可以将删除拆分为较小的工作单元。如果你确实有争用,它肯定更容易找到冲突的原因。
如上所述,“删除级联”绝对保证参照完整性。
因此,使用两者 - 在连接的sqls中显式删除“children”以避免死锁和性能问题。但是启用“CASCADE DELETE”可以捕获您错过的任何内容。因为当你来删除父母时不应该留下任何孩子,这将不会花费你任何东西,除非你在删除时犯了错误,在这种情况下,维持你的参照完整性是值得的。