如果涉及外键,硬删除如何工作

时间:2016-10-20 21:49:18

标签: database-design entity enterprise referential-integrity

在关系数据库中心应用程序中,我需要一些关于软删除与硬删除争议的智慧。像thisthisthis这样的注释都会阻止软删除,因为它基本上是一种黑客,一种肮脏,简单的方法,并声称硬删除是更好的方式。

我很乐意同意。但似乎没有人提到如何处理一个主要的,不可避免的问题:如果外键约束阻止删除行,并且当级联删除不是一个选项时,如何硬删除行? < / p>

基本,如果您想要硬删除实体A,而实体B指向它,并且由于商业原因B根本无法删除,不会强制你使用某种形式的软删除(即将记录保持在原处)?

如果您有客户&#34; Acme&#34;谁进行了交易10001,你不能简单地删除Acme,因为几乎任何企业都需要:

  1. 无法删除任何交易
  2. 交易必须指向成功的客户
  3. 无论Acme如何被删除&#34;删除&#34; (硬,软,中等)销售报告,例如,仍然必须显示交易#10001是由客户Acme在2010-05-01制作的 - 即使Acme已经不在了。因此,它要求Acme仍然存储在系统中的某处

    一个线程不断出现硬删除的拥护者:使用适当的审计表,并执行诸如保留已删除对象的序列化副本之类的事情。但我们无法将Transaction#10001的FK重定向到审计表中的此特定行。然后怎样呢?创建一个&#34; OldCustomers&#34;反映&#34;客户&#34;的架构的表格。并以某种方式重定向指向Acme的系统中的每个FK?我不是数据库专家,所以我不知道这是否可能,但即使是这样,现在所有的报告查询都必须考虑两个表(听起来比不得不追加更糟糕)所有查询AND IsDeleted = false

    简而言之,我觉得我错过了一些东西,因为硬件和软件删除都是辩论 - 这意味着它们都是可行的选择。但据我所知,在95%的商业案例中,没有可能使用硬删除(在技术层面,由于FK约束,在逻辑层面上,仅仅因为一件事情不能消失另一件事指向它)

3 个答案:

答案 0 :(得分:1)

我认为让硬删除工作并同时保留某种记录的一种方法是不将 FK 用于关系,而只是一个像 FK 一样工作但不保证参照完整性的标识符字段。然后,您只需要处理不再使用该 id 的用户的情况。

答案 1 :(得分:0)

TL; DR 适当的表格&amp;约束作为正确建模的一部分出现。你的问题错误地假定了表和表的限制。约束看起来像。

来自你的评论:

  

是否可以接受该特定事务对于它的FK值应该只有NULL?查询该行时,它基本上表示“没有与此事务关联的客户”

嗯, 没有当前客户与此交易相关联。如果有一个过去客户与您想要记录的此交易相关联,那么您必须记录它。同样关于客户或交易的任何其他数据。硬删除的提议假设您保留所需的历史数据。不要将你的想法限制为仅仅归零FK,级联,将标志/日期列添加到现存表或其他任何内容。正确模拟礼物和礼物过去包括在每个选定的应用程序情况发生变化时需要作为DBMS事务发生的数据库更改。软删除的提议只涉及将某些当前和历史数据放入同一个表中而不是不同的表中。这仅适用于当前&amp;的非常简单的模型。历史情况。

通常可以直接为当前应用程序情况设计数据库。但是如果我们关心过去,我们通常只会关心一些。如果是这样,当某些应用情况从当前变为过去时,我们可以将相关当前状态的快照复制到历史状态。使用软删除标记与日期标记数据是未注明日期和过时的历史数据的组合表版本,我们只关心当前与过去的情况,我们只关心 vs 发生了变化。

“时间”数据库或多或少地记录了当前的情况和一堆过时的现状。使用当前数据的结构记录过去的数据简化了理解和查询当前&amp;过去的数据。 (查询时间数据库可以促成的 interval 时间变得非常复杂。)但事实证明,制作给定当前数据设计的时间版本并不仅仅涉及添加日期列现存的当前数据表。它需要重新构建当前数据,将其分解为具有更多约束的较小表。这是因为不同类型的应用情况变化需要约会现有当前数据设计的不同列组合。 (硬和软历史快照设计必须解决这个问题,但对于有限的过去/历史。)

“无软删除”背后的想法是,有两个不同的上下文,每个上下文限制用户和实现者可以犯的错误更安全。 “历史”与“时间”背后的想法是,模拟和查询过去应用情况的有限预定范围可能更简单。然而,当您将声音设计原则应用于建模关于应用程序当前和过去您想要的过去情况的大量数据时,每种方法选项的设计自然会出现。

PS如果你想了解时态数据库,请阅读Lorentzos,Date&amp; Darwen并避免使用Snodgrass。

答案 2 :(得分:0)

我使用时间设计,广泛使用软删除。或者通过现在执行相同的查询来获取当前数据。该设计允许硬删除(很少使用),软删除(最常用)和固定删除(如软删除但不允许撤消)。此设计允许用户执行“截至日期”的查询,并返回在该日期执行查询时返回的相同结果。

毋庸置疑,如果“旧”数据和“当前”数据包含在不同的表格中,这将非常困难。

查看您的参考资料,我注意到性能受到了很大的关注,但是没有实际的性能命中示例,第一个参考甚至承认“实践,过滤非活动行不会花费太多本身。“

这与我对“版本化”表的测试相匹配,其中包含数百万个实体的数百万个版本。

通过提供仅公开当前数据的视图以及其他公开整个历史记录(以及其他需要的视图)来解决复杂性问题。这对我来说没有问题,因为我倾向于让应用程序访问视图而不是表格。

当您接受它时,一般的抱怨是使用软删除会使db开发人员的工作更加困难。这是真的。但我们的工作是让用户的工作更轻松 - 而不是我们自己的工作。

我的女儿是一家大银行的金融分析师。她经常告诉我,如果她能够及时回顾过去某个特定日期的数据,她的工作会变得多么容易。当然有档案。但通常这仅显示归档时数据的最终状态。当帐户被打开,经历变更并最终关闭时,她无法完成整个过程。 (这些是大型公司退休账户,而不是定期支票或储蓄账户。)

但她不能让她的IT部门感兴趣,因为它“太多了”。悲伤。