如何在SQL上用外键关系实现软删除?

问题描述 投票:2回答:1

我需要在具有5个子外键关系的表上更改Web应用程序上“删除”功能的行为。它是一个相当大的Web应用程序,因此我正在寻找风险最小且影响最小的更改,因此它需要对Web应用程序进行最少量的更改。

我可以想到两个选择:

  1. 使用默认deleted向表0添加一列,1将指示该记录已被删除。这将需要更新表上的所有选择(以及它的子表,因为它们现在是孤立的)以包括子句where deleted = 0。 Web应用程序已经过时且编写得不好(重复代码),因此有许多地方需要进行此更改,因此可能会遗漏一个或多个位置存在风险。
  2. 将记录移动到表的另一个副本,特别是删除的记录。我可能也需要镜像每个子表。

选项1似乎预先付出了更多努力,但未来可维护性更强,选项2预先做的工作量不大,对Web应用程序的改动很小,但非常混乱。还有其他选择吗?

sql sql-server database database-design sql-delete
1个回答
3
投票

这是我如此喜欢观点的一个很好的例子。

  • 创建新列“已删除”
  • 重命名表:MyData => AllMyData
  • 使用旧名称创建一个视图,该视图完全按照之前的方式公开表中的数据,但仅限于“未删除”的行。

例:

create view MyData as
    select ...
    from   AllMyData
    where  Deleted = 0
  • 在视图上写入触发器以处理DML,就像它是原始表一样。
  • 创建另一个视图以显示已删除的行。

例:

create view DeletedMyData as
    select ...
    from   AllMyData
    where  Deleted = 1
  • 在应用程序中实现“软删除”和“取消删除”功能。此代码将是直接访问表的唯一代码,将Deleted的值设置为0或1。现有代码无需修改。
  • 子表可能根本不需要任何更改。由于可能通过加入未删除的视图(具有原始表名称的视图)来查询它们,因此不会公开引用“已删除”数据的记录,但会在数据未删除时自动重新显示。
  • 更新:MyData视图上的ON_DELETE触发器只会针对实际表发出更新,将Deleted值设置为1.可以使用DeletedMyData视图上的ON_DELETE触发器将UNDELETE操作实现为将值设置为0。删除MyData视图将执行软删除(记录将从MyData数据集中消失并出现在DeletedMyData中)并在DeletedMyData视图上发出删除将执行软反删除(记录将从DeletedMyData数据集中消失并重新出现在MyData)。
© www.soinside.com 2019 - 2024. All rights reserved.