29

问题

在处理产品和订单的 Web 应用程序中,我想维护前雇员(用户)与他们处理的订单之间的信息和关系。我想维护过时产品和包含这些产品的订单之间的信息和关系。

但是,我希望员工能够整理管理界面,例如删除前员工、过时的产品、过时的产品组等。

我正在考虑实施软删除。那么,通常如何做到这一点呢?

我的直接想法

flag_softdeleted我的第一个想法是在每个应该软删除的对象表中粘贴一个“ TINYINT NOT NULL DEFAULT 0”列。或者也许改用时间戳?

然后,我在每个相关的 GUI 中提供了一个“显示已删除”或“取消删除”按钮。单击此按钮,您将在结果中包含软删除的记录。每条删除的记录都有一个“恢复”按钮。这有意义吗?

你的意见?

另外,我很感激任何指向相关资源的链接。

4

6 回答 6

38

我就是这样做的。我有一个is_deleted默认为 0 的字段。然后查询只需检查WHERE is_deleted = 0.

我尽量远离任何硬删除。它们有时是必要的,但我将其设为仅限管理员使用的功能。这样我们可以硬删除,但用户不能...

编辑:事实上,您可以使用它在您的应用程序中拥有多个“层”软删除。所以每个都可以是一个代码:

  • 0-> 未删除
  • 1-> 软删除,显示在管理用户的已删除项目列表中
  • 2-> 软删除,除管理员用户外,不会显示给任何用户
  • 3-> 仅向开发人员显示。

拥有其他 2 个级别仍然允许经理和管理员清理已删除的列表,如果它们太长的话。而且由于前端代码只检查is_deleted = 0,它对前端是透明的......

于 2011-02-16T18:33:07.377 回答
11

使用软删除是一种常见的实现方式,它们对很多事情都非常有用,例如:

  • 在用户删除某些内容时保存用户的数据
  • 删除某些内容时保存自己的数据
  • 记录真实发生的事情(一种审计)
  • 等等

我想指出一件事,几乎每个人都错过了,它总是回来咬你的后部。您的应用程序的用户对删除的理解与您不同。

有不同程度的删减。典型的用户会在他(她)的时候删除东西

  • 犯了一个错误,想删除坏数据
  • 不想再在屏幕上看到任何东西

问题是,如果您不记录删除的意图,您的应用程序将无法区分错误数据(不应该创建)和历史上正确的数据。

看看以下数据:

PRICES | item | price | deleted |
       +------+-------+---------+
       |   A  |  101  |    1    |
       |   B  |  110  |    1    |
       |   C  |  120  |    0    |
       +------+-------+---------+

一些用户不想显示商品 B 的价格,因为他们不再出售该商品。所以他删除了它。另一个用户错误地为项目 A 创建了价格,因此他删除了它并按预期为项目 C 创建了价格。现在,你能告诉我所有产品的价格清单吗?不,因为要么您必须显示潜在的错误数据 (A),要么您必须排除除当前价格之外的所有数据 (C)。

当然,可以通过多种方式处理上述问题。我的观点是,需要非常清楚所说的删除是什么意思,并确保用户不会误解它。一种方法是强制用户做出选择(隐藏/删除)。

于 2011-02-16T20:00:06.260 回答
6

如果我有命中该表的现有代码,我将添加列并更改表的名称。然后我会创建一个与当前表同名的视图,它只选择活动记录。这样,现有代码都不会中断,您可以拥有软删除列。如果要查看已删除的记录,请从基表中选择,否则使用视图。

于 2011-02-16T18:37:12.977 回答
1

正如您提到的,我一直只是使用已删除的列。真的没有比这更多的了。无需删除记录,只需将已删除字段设置为 true。

我构建的一些组件允许用户查看所有已删除的记录并恢复它们,其他组件仅显示已删除= 0的所有记录

于 2011-02-16T18:33:58.433 回答
1

您的想法确实有意义并且在生产中经常使用,但是要实现它,您需要更新相当多的代码以适应新领域。另一种选择可能是将“软删除”记录归档(移动)到单独的表或数据库中。这也经常进行,并使问题成为维护而不是(重新)编程的问题之一。(您可以让表触发器对删除做出反应以存档已删除的记录。)

我会进行归档以避免对生产代码进行重大更新。但是,如果您想使用已删除标志字段,请将其用作时间戳,以便为您提供除布尔值之外的其他有用信息。(Null = 未删除。)您可能还想添加 DeletedBy 字段来跟踪负责删除记录的用户。使用两个字段可以为您提供大量信息,告诉您谁删除了什么以及何时删除。(两个额外的字段解决方案也可以在存档表/数据库中完成。)

于 2011-02-16T18:36:45.713 回答
0

我遇到的最常见的场景是您所描述的,atinyint甚至bit代表 or 的IsActive状态IsDeleted。根据这是否被视为“业务”或“持久性”数据,它可能会尽可能透明地被烘焙到应用程序/域逻辑中,例如直接在存储过程中并且不为应用程序代码所知。但听起来这是满足您需求的合法业务信息,因此需要在整个代码中都知道。(因此用户可以按照您的建议查看已删除的记录。)

我见过的另一种方法是使用两个时间戳的组合来显示给定记录的活动“窗口”。维护它需要更多代码,但好处是可以安排某些东西在预定时间自行软删除。例如,限时产品可以在创建时以这种方式设置。(要使记录无限期地处于活动状态,可以使用最大值(或只是某个荒谬的遥远的未来日期),或者null如果您对此表示满意,则只使用结束日期。)

然后当然会进一步考虑不时删除/取消删除的内容,并为此跟踪某种审计。标志方法只知道当前状态,时间戳方法只知道最近的窗口。但是像审计跟踪这样复杂的东西绝对应该与相关记录分开存储。

于 2011-02-16T18:38:01.680 回答