SQL Schema设计问题 - 删除标志

时间:2010-02-12 14:41:01

标签: sql postgresql

在我们的数据库模式中,我们喜欢使用删除标志。删除记录后,我们会更新该字段,而不是运行删除语句。然后我们的其余查询在返回数据时检查删除标志。

问题在于:

删除标志是一个日期,默认值为NULL。这很方便,因为当删除记录时,我们可以很容易地看到它被删除的日期。

但是,要正确实施唯一约束,我们需要在唯一约束中包含删除标志。问题是,在MS SQL上,它的行为符合我们的要求(对于此设计),但在postgresql中,如果多列唯一约束中的任何字段为NULL,则它允许该字段。此行为符合SQL标准,但它会破坏我们的设计。

我们正在考虑的选项是:

  1. 将已删除字段的默认值设为某个硬编码日期

  2. 为删除添加一个标志,然后每个表将有2个删除相关字段 - date_deleted和is_deleted(例如)

  3. 将date_deleted更改为is_deleted(位字段)

  4. 我怀疑选项1是性能损失,每个查询都必须检查硬编码日期,而不是只检查IsNUll。再加上它感觉不对。

    选项2也感觉不对 - “删除”的2个字段是非干的。

    选项3,我们丢失了“日期”信息。有一个修改过的字段,理论上会反映删除的日期,但只假设对该行的最后一次更新是对删除位的更新。

    那么,有什么建议吗?你过去做了什么来处理“删除标志”?

    更新 感谢大家的超快速和深思熟虑的回应。 我们最终得到了一个简单的布尔字段和一个修改过的日期字段(带有触发器)。我刚刚注意到部分索引建议,这看起来像是这个问题的完美解决方案(但我还没有尝试过)

7 个答案:

答案 0 :(得分:4)

如果仅保留已删除的记录对您来说很重要,您是否考虑过将它们移至历史记录表?

  • 这可以通过触发器轻松实现。
  • 应用程序逻辑不需要考虑此已删除的标记。
  • 从中选择时,您的表格将保持精简和意味着
  • 它可以解决您使用唯一索引的问题。

答案 1 :(得分:3)

  

选项3,我们失去了“约会”   信息。有修改   从理论上反映出来的领域   删除日期,但只是假设   该行的最后一次更新是   更新到删除位。

是否有商业原因导致该记录在删除后会被修改?如果没有,你是否担心实际上不是问题? =)

在我目前正在处理的系统中,我们有以下“元数据”列_Deleted,_CreatedStamp,_UpdatedStamp,_UpdatedUserId,_CreatedUserId ......相当多,但这个系统携带那么多数据很重要。我建议为删除到修改日期/删除日期单独标记。 “磁盘空间很便宜”,并且有两个字段来表示已删除的记录并不是世界末日,如果这是你要为你正在使用的RDBMS做的事情。

答案 2 :(得分:3)

触发器怎么样?删除记录时,更新后的触发器会将行复制到具有相同结构和任何其他列的归档表中,以及日期/时间的附加列以及可能删除它的用户。

这样你的“实时”表只有实际存在的记录,因此性能更好,你的应用程序也不必担心记录是否被删除。

答案 3 :(得分:3)

只需创建一个条件唯一约束:

CREATE UNIQUE INDEX i_bla ON yourtable (colname) WHERE date_deleted IS NULL;

答案 4 :(得分:2)

我最喜欢的解决方案之一是is_deleted位标记和last_modified日期字段。

每次修改行时都会自动更新last_modified字段(使用DBMS支持的任何技术。)如果is_deleted位标志为TRUE,则last_modified值表示该行被删除的时间。

然后,您就可以将last_modified的默认值设置为GETDATE()。不再有NULL值,这应该适用于您的唯一约束。

答案 5 :(得分:0)

创建包含已删除日期的多列唯一索引是否会达到您需要的相同约束限制?

http://www.postgresql.org/docs/current/interactive/indexes-unique.html

或者,您是否可以存储非NULL并检查删除的日期是否为最小sql日期= 0或“1/1/1753”而不是未删除记录的NULL。

答案 6 :(得分:0)

是否可以从唯一索引中排除已删除的日期字段?该字段以何种方式对每条记录的唯一性做出贡献,特别是如果该字段通常为空?