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

时间:2016-07-13 14:25:07

标签: sql sql-server database database-design sql-delete

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

我可以想到两个选择:

  1. 使用默认deleted向表0添加一列,1表示该记录已被删除。这将需要更新表上的所有选择(以及它们的子表,因为它们现在是孤立的)以包含子句where deleted = 0。网络应用程序很旧,编写得不好(重复代码),因此有很多地方需要进行此更改,因此可能会错过一个或多个位置,这是冒险的。

  2. 将记录移动到表的另一个副本,特别是删除的记录。我可能也需要镜像每个子表。

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

1 个答案:

答案 0 :(得分:3)

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

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

示例:

create view MyData as
    select ...
    from   AllMyData
    where  Deleted = 0
  • 在视图上写入触发器以处理DML,就像它是原始表一样。

  • 创建另一个视图以公开已删除的行。

示例:

create view DeletedMyData as
    select ...
    from   AllMyData
    where  Deleted = 1
  • 实施"软删除"和#34;取消删除"应用程序内的功能。此代码将是直接访问表的唯一代码,将Deleted的值设置为0或1。 现有代码无需修改。

  • 子表可能根本不需要更改。由于可能通过加入未删除的视图(具有原始表名称的视图)来查询它们,因此引用"删除的记录"数据不会被公开,但会在数据未删除时自动重新公开。

  • 更新:MyData视图上的ON_DELETE触发器只会针对实际表发出更新,将Deleted值设置为1.可以使用{{上的ON_DELETE触发器实现UNDELETE操作。 1}}视图将值设置为0.因此,在DeletedMyData视图上发出删除将执行软删除(记录将从MyData数据集中消失并显示在MyData中)并在DeletedMyData视图上发出删除将执行软删除(记录将从DeletedMyData数据集中消失并重新出现在DeletedMyData)。