依赖外键级联是不是很糟糕?

Key*_*eyo 16 mysql sql database-design cascade

我参与的项目的首席开发人员表示依靠级联删除相关行是不好的做法.

我不知道这有多糟糕,但我想知道你对它是否/为什么的看法.

cle*_*tus 20

我将通过说我很少删除行周期来作为序言.通常,您希望保留大多数数据.您只需将其标记为已删除,这样就不会向用户显示(即向用户显示已删除).当然,这取决于数据和某些东西(例如购物车内容),当用户清空他或她的购物车时,实际上删除了记录.

我只能假设这里的问题是您可能无意中删除了您实际上不想删除的记录.但参考完整性应该可以防止这种情况 因此,除了明确的情况之外,我无法真正看到反对此的理由.

  • 这是一个原因 - 删除的数据逐渐回溯到查询结果,因为有人忘记了`AND DELETED = 0`.如果这样做,请将所有已删除的数据隐藏在仅限实时数据的视图或类似内容之后,否则您将遇到问题. (8认同)
  • 这就是视图的用途。如果需要,将表命名为“foo_historical”,将视图命名为“foo”。 (2认同)

Rob*_*vey 15

我会说你遵循最少惊喜的原则.

级联删除不应导致意外的数据丢失.如果删除需要删除相关记录,并且用户需要知道这些记录将要消失,则不应使用级联删除.相反,应该要求用户明确删除相关记录,或者提供通知.

另一方面,如果表涉及另一个临时性的表,或者包含父实体消失后永远不需要的记录,则级联删除可能没有问题.

也就是说,我更愿意通过删除代码中的相关记录来明确表达我的意图,而不是依赖于级联删除.事实上,我从未真正使用级联删除来隐式删除相关记录.另外,我使用了很多软删除,如cletus所述.

  • 这是一个很好的原则,自然发生的惊喜已经足够多了——不需要制造更多的惊喜。 (2认同)
  • 除了“标记解决方案”之外,完全同意这一点,软删除不是黄金。当你除了PK之外还有其他独特的限制时,这很容易成为一个大问题。仅在需要时才进行软删除。 (2认同)

Mit*_*eat 12

我从不使用级联删除.为什么?因为犯错很容易.要求客户端应用程序明确删除(并满足删除条件,例如删除FK引用记录)要安全得多.

事实上,通过将记录标记为已删除或移入存档/历史记录表,可以避免删除本身.

在将记录标记为已删除的情况下,它取决于标记为已删除数据的相对比例,因为SELECTs将必须过滤' isDeleted = false'索引仅在小于10%(大约取决于RDBMS)的情况下使用记录被标记为已删除.

您更喜欢以下两种情况中的哪一种:

1)开发人员来找你,说"嘿,这个删除行不通".你们都看着它,发现他无意中试图删除整个表格内容.你们都笑了,回到你们正在做的事情.

2)开发人员来找你,羞怯地问"我们有备份吗?"

  • @NickCraver,如果您正确设置了外键(如果没有,您将无法设计数据库),那么您描述的场景就不会发生。如果你愚蠢到依赖应用程序来建立关系,那么数据库完整性问题的可能性接近 100%。 (3认同)

HLG*_*GEM 7

避免级联删除的另一个重要原因是性能。在您需要从主表中删除10,000条记录(而子表中又有数百万条记录)之前,它们似乎是一个好主意。鉴于此删除操作的大小,很可能会完全锁定所有表达数小时甚至数天。你为什么要冒险呢?为了减少花费十分钟的时间来为一条记录删除额外的delete语句的方便?

此外,尝试删除具有子记录的记录时遇到的错误通常是一件好事。它告诉您您不希望删除该记录,因为某些数据需要删除,否则将丢失。级联删除只会继续并删除子记录,从而导致有关订单信息的丢失,例如,如果您删除了过去有订单的客户。这种事情会彻底弄乱您的财务记录。

  • 对于不知道自己在做什么的学习 SQL 的人来说,将其作为解决方案是一种不好的做法。 (4认同)
  • @HLGEM这仅表示此功能已被滥用;这并不意味着这是一个坏习惯。 (2认同)