【发布时间】:2017-03-03 02:02:15
【问题描述】:
我需要一些智慧来解决以关系数据库为中心的应用程序中关于软删除与硬删除的争论。像 this、this 和 this 这样的评论都劝阻软删除,因为它基本上是一种 hack、肮脏、简单的出路,并声称硬删除是更好的方法。
我很乐意同意。但似乎没有人提到如何处理一个主要的、不可避免的问题:当外键约束阻止删除一行时,如何硬删除一行,而级联删除不是一种选择?
本质上,如果您想硬删除实体 A,而实体 B 指向它,并且出于业务原因根本无法删除 B,那强制 em> 你要使用某种形式的软删除(即将记录保留在原处)?
如果您的客户“Acme”进行了交易 10001,则不能简单地硬删除 Acme,因为几乎所有企业都需要这样做:
- 没有交易可以删除
- 交易必须指向进行交易的客户
例如,无论 Acme 如何“删除”(硬、软、超中)销售报告,仍然必须显示交易 #10001 是由客户 Acme 于 2010 年 5 月 1 日进行的——即使如果 Acme 不再存在。因此,它要求 Acme 至少仍存储在系统中的某处。
硬删除的拥护者不断提出一个话题:使用适当的审计表,并在其中保留已删除对象的序列化副本。但是我们不能将事务#10001 的 FK 重定向到审计表中的这一特定行。然后怎样呢?创建一个反映“客户”模式的“OldCustomers”表,并以某种方式重定向系统中指向 Acme 的每个 FK?我不是数据库专家,所以我不知道这是否可能,但即使是这样,现在您的所有报告查询都必须考虑两个表(听起来比必须将AND IsDeleted = false 附加到所有查询更糟糕)
简而言之,我觉得我错过了一些东西,因为硬删除和软删除是有争议的——这意味着它们都是可行的选择。但据我了解,在 95% 的业务案例中,不可能使用硬删除(在技术层面上,由于 FK 限制,在逻辑层面上,仅仅是因为一件事不能在另一件事时消失指向它)
【问题讨论】:
-
你基本上是在征求意见。没有正确/错误的方式。只有满足您的业务需求。任何说“使用 X,因为它是唯一正确的方法”的人都充满了温暖的公牛叶子”
-
@MarcB 不,我不是在征求意见,而是在问它是如何可能的(无论是在技术意义上还是逻辑意义上)硬删除可以在那里工作是否涉及约束。
-
Re“如果你想硬删除实体 A,而实体 B 指向它,并且出于业务原因 B 根本无法删除”:你不是说,A 根本不能被删除?
-
@philipxy:不,我的意思是 B 不能通过一些级联删除来删除。 A(客户)将被删除,但 B(该客户的交易)由于明显的商业原因不能被删除。如果客户记录只是消失了,即使我们在 Transactions 表中有一个可为空的 FK 列,该特定事务的 FK 值应该只具有 NULL 是否可以接受?当您查询该行时,它基本上表示“没有与此交易关联的客户”?从商业角度来看,这也是不可接受的
标签: database-design entity enterprise referential-integrity