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