Sql 如何处理数据库中的删除(将删除的实体移动到存档表)?

Sql 如何处理数据库中的删除(将删除的实体移动到存档表)?,sql,database,Sql,Database,我们目前正在开发的信息系统有一个PostgreSQL驱动的数据库。由于删除问题是我一直不愿意完全解决的问题,它开始困扰我,因为项目已经开始,数据库正在慢慢填充,到了某个时候,用户实际上会想要删除不相关的数据 在我们的例子中,用户删除的是我们为客户做的某种“工作”。一旦作业完成,用户通常不希望将其列在网页上,因此会将其删除。起初(当系统处于测试阶段,所以不会造成伤害时),用户的删除是从数据库中真正删除的。因为它被很好地设置为级联到实体图的最底部,所以它实际上删除了所有内容。也花了很多时间。现在,我

我们目前正在开发的信息系统有一个PostgreSQL驱动的数据库。由于删除问题是我一直不愿意完全解决的问题,它开始困扰我,因为项目已经开始,数据库正在慢慢填充,到了某个时候,用户实际上会想要删除不相关的数据

在我们的例子中,用户删除的是我们为客户做的某种“工作”。一旦作业完成,用户通常不希望将其列在网页上,因此会将其删除。起初(当系统处于测试阶段,所以不会造成伤害时),用户的删除是从数据库中真正删除的。因为它被很好地设置为级联到实体图的最底部,所以它实际上删除了所有内容。也花了很多时间。现在,我们开始真正使用这个系统,我担心意外删除,我让用户无法删除任何内容

我认为最重要的问题是“在我们的业务领域,‘删除’一份工作到底意味着什么?”在我们的案例中,有两点:

  • 用户不想再看到列出的作业(除非他们明确要求提供旧作业列表,因此我必须保留该列表)
  • 一些工作的数据永远消失了,只保留了一些工作状态的基本概述
我读过很多关于软删除为什么好的文章,也读过很多关于软删除为什么不好的文章(例如)。在我看来,更好的选择是将已删除的作业移动到某个存档表中。同时,我会删除不再需要的工作数据。这样做的好结果是,我不必调整所有查询来处理某种“DeletedOn”列,主作业表也不会被非活动作业弄乱

我遇到的问题更多的是技术问题:假设我仍然需要保留其他实体对已删除作业的一些引用,那么最好的方法是什么?因为我在其他实体中设置了作业表的外键,所以我不能将作业移动到另一个表中,DB不允许我这样做


什么是通常的、经过良好测试的方法?

如果我理解正确,那么您在数据库中有一些“工作”,无法删除所有相关信息,但需要保留其中的一部分

在这种情况下,我会使用两个选项:

  • 添加作业状态字段
    此字段可以有不同的值,如new/in progress/waiting/Deliveried/deleted。。。一旦你改变你的代码来适应这个新领域,你就有了很大的灵活性。。。您可以根据用户界面中的作业状态等提供过滤器

  • 添加一个DeleteOn字段并将其隐藏
    您可以重命名该表,添加字段,并创建一个与原始表同名的视图,该视图将过滤掉设置了DeleteOn的所有记录。。。视图得到一个触发器(在删除时),它只为相应的作业设置该字段。。。无级联删除、无混乱/更改代码等。如果需要,您始终可以扩展触发器以移动将DeleteOn设置为存档表的所有或部分行


我不能告诉你什么是通常的、经过良好测试的方法,我只能告诉你什么对我有效

我们同意这样一个事实,即不应因各种原因(审计、历史归档等)丢失任何数据,因此我们看到了两种可能的结果:

  • 移动数据
  • 将数据标记为已删除,并在每次查询时对其进行筛选
现在的问题是什么对你来说更贵

  • 移动数据: 在这里,您将需要另一个表(或者可能是OLAP数据库?)来持久保存所有删除。我想到的第一个成本是双重保养。如果向一个表中添加列,则必须将其添加到历史表中(或更新ETL作业和目标表)。您对ERD所做的每项更改都必须进行两次

  • 标记数据: 更新所有当前查询以考虑标志。这可能会很痛苦,但这只是一个问题(在大多数情况下,如果deleted=0,则会是一个
    )
    一些orm提供了很好的方法来解决这个问题,而无需手动更改查询。
    另一个问题是您也提到过的,您的表将是“脏的”。这可能是性能问题,也可能不是性能问题,具体取决于生成的数据量


每次我考虑每种选择的好处/成本时,我总是选择使用软删除,所以现在取决于在您的情况下什么更昂贵。

+1个有趣的问题。我会将所有内容移动到存档表并删除它们。