【问题标题】:A Never Delete Relational DB Schema Design永不删除的关系数据库模式设计
【发布时间】:2011-06-21 21:32:16
【问题描述】:

我正在考虑为从不实际删除任何内容(设置已删除标志或其他内容)的数据库设计一个关系数据库架构。

1) 通常使用哪些元数据列来适应这种架构?显然可以设置 IsDeleted 的布尔标志。或者也许只是在 Deleted 列中的时间戳效果更好,或者可能两者兼而有之。从长远来看,我不确定哪种方法会给我带来更多问题。

2) 在此类架构中通常如何处理更新?如果您将旧值标记为已删除并插入一个新值,您将遇到 PK 唯一约束问题(例如,如果您有 PK 列 id,那么新行必须与您刚刚标记为无效的行具有相同的 id,或者否则,该 id 的其他表中的所有外键都将变得无用)。

【问题讨论】:

  • 如果你有一个表 A 对表 B 有一个外部约束,并且表 B 中的一行被删除了,你想发生什么?我们是否假设 A 中的引用行已被删除? A 应该指向 B 中的新行吗? A行是否应该仍然存在并继续指向已删除的B行?

标签: mysql sql-server oracle postgresql relational-database


【解决方案1】:

如果您的目标是审计,我会为您拥有的每个表创建一个影子表。添加一些在更新和删除时触发的触发器,并将行的副本插入到影子表中。

【讨论】:

  • @btilly:不完全正确;如果您关心性能,这也是一个很好的解决方案,而您只是碰巧希望性能变慢。 :)
  • @Btilly 表现如何?选择、插入、更新、删除?
  • 原始问题暗示将在更新和删除时进行复制。该问题还标记了许多 RDBM,因此不应使用特定于供应商的内容。
  • @Conrad Frix:触发器只在插入、更新和删除时运行,所以这些是减慢的。
  • @Steve Prentice:触发器的实现往往是高度特定于数据库的,但它们在大多数数据库中都可用。连 MySQL 和 SQLite 都有触发器!
【解决方案2】:

您还需要考虑以下一些其他问题

  1. 删除的频率。你的绩效预算是多少?这会影响您的选择。您的设计的答案会有所不同,具体取决于用户是否删除单行(例如,让我们说问答网站上的答案与每小时从提要中删除记录)

  2. 您将如何公开系统中已删除的记录。是仅通过管理目的还是任何用户都可以看到已删除的记录。这会有所不同,因为您可能需要根据用户提出过滤机制。

  3. 外键约束如何工作。一张表可以引用另一张有删除记录的表吗?

  4. 当您添加或更改现有表时,删除的记录会发生什么?

正如 Steve Prentice 所提到的,通常非常关心审计的系统会使用表。它通常使原始表中的每个字段都关闭所有约束。它通常会有一个操作字段来跟踪更新与删除,并与用户一起包含更改的日期/时间戳。

有关示例,请参阅 https://data.stackexchange.com/stackoverflow/query/new 的 PostHistory 表

【讨论】:

    【解决方案3】:

    我认为您在这里寻找的内容通常被称为“知识约会”。

    在这种情况下,您的主键将是您的常规键加上知识开始日期。

    对于当前记录,您的结束日期可能为空,也可能是“时间结束”标记。

    在更新时,您通常会将当前记录的结束日期设置为“现在”,并使用新值插入一条从相同“现在”开始的新记录。

    在“删除”时,您只需将结束日期设置为“现在”。

    【讨论】:

    • 这不是一个糟糕的解决方案,但它如何影响性能?特别是在您希望获得当前记录的情况下,这会增加您的选择的大量开销。
    【解决方案4】:
    1. 我已经做到了。

    2.a) 版本号在一定程度上解决了唯一性约束问题,尽管这实际上只是放松了唯一性,不是吗。

    2.b) 您还可以将旧版本存档到另一个表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多