软删除是个好主意吗?

001*_*001 136 sql database database-design data-modeling soft-delete

软删除是个好主意还是坏主意?

您只需将其标记为IsDeleted = true,而不是实际删除数据库中的记录,并且在恢复记录后,您可以将其标记为False.

这是一个好主意吗?

最好是物理删除记录,然后将其移动到存档数据库,如果用户想要记录回来,那么软件会在存档中查找记录并重新创建它吗?

Mus*_*sis 100

我说这是一个坏主意,通常(也许有一些例外).

首先,应该定期备份您的数据库,因此您永远不会因为DELETE而永久丢失数据(当然,除非是删除刚添加的数据).

其次,像这样的软删除意味着你现在必须WHERE IsDeleted = false在这个表的每个查询中包含一个子句(如果你正在加入这些表,那就更糟了).一旦用户或测试人员发现删除的记录再次出现,就会发现这里的错误,这可能需要一些时间.此外,开发人员很容易从COUNT(*)查询中省略WHERE子句,这可能需要更长的时间才能发现(我曾在一个已经发生多年的项目上工作过;没有多少记录被"删除" ,所以总数接近预期,没有人注意到).

最后,软删除将在具有人工键的表上工作,但可能无法在具有自然主键的表上工作(例如,您从社会安全号码键入的表中"删除"某人 - 当您执行时,您会怎么做需要添加他吗?请不要说"在复合主键中包含IsDeleted".).

在设计评审中,我希望开发人员能够展示成本和收益的意识,并以这种方式提供进行软删除的绝佳理由."为什么这样做?" 不是一个很好的理由.

  • @Josh:*SQL编程中的所有*都相当简单; 这是许多琐碎事物的积累,开始引发问题.正如我在上一句中所说,我希望开发人员有充分的理由以这种方式增加系统的复杂性.我很失望,但看到这么多开发人员说他们这样做是理所当然的,不管他们的应用程序的实际需求如何,我都不会感到惊讶. (40认同)
  • 如果需要,创建一个视图并实现它是非常简单的,它排除了所有is_deleted记录.然后可以针对视图运行所有查询.至于从备份中恢复 - 例如重新启用用户帐户 - 您实际上不希望运行到存档来恢复其数据.你想设置is_deleted = false.这是一个相当原始(并且不太可能)的场景,因为您可能使用了禁用字段 - 但重点是相同的.在某些情况下,能够立即恢复已删除的数据可能是值得的. (6认同)
  • 另外值得一提的是:"UNIQUE"索引与软删除相结合可能会造成混乱.例如,尝试注册已删除的用户名将失败,即使它未被使用. (6认同)
  • @TravisJ我不再同意大多数情况下软删除的概念.我想,'只是因为'不是软删除的好理由. (3认同)
  • 不使用软删除的+1除非你真的有理由这样做.这里没有提到的是参照完整性停止以正确的方式使用软删除的行.如果将row标记为已删除,则应将每个子行标记为已删除,如果不这样做,则DBMS不会阻止此类逻辑删除.所以"没有级联删除的问题"不是这里的情况.你为什么不删掉整个FK呢?它还允许您删除行而不检查引用的记录. (3认同)
  • 让我支持MG.你有一个时间戳字段.您经常通过索引扫描它... sysdate -2和sysdate之间的所有内容.如果经常软删除,则范围扫描可能会返回大部分必须过滤掉的行.过滤=昂贵,范围扫描=便宜. (2认同)
  • @Vincent,如果您需要在应用程序中使用已删除的数据,那么您不会处理_delete_操作,它还有其他商业含义.如果"IsDeleted"仅用于存档目的,我会使用单独的表.如果您担心错误删除可能导致数据丢失,那么更新错误会怎样?也许你应该考虑在这种情况下使用全功能审计? (2认同)

Rob*_*vey 93

避免潜在的数据丢失绝不是一个坏主意.

我总是软删除.在需要擦除一个或多个记录的数据库的情况下,我通常采用两步软删除过程,然后清空记录的"回收站",或文档管理式方法,其中文档记录可以老去,然后在硬删除之前通过批准程序.

  • +1:`我总是软删除 (35认同)
  • 系统通常仍需要完整性,审计或变更历史的数据...软删除!使用清理过程进行实际删除等... PK :-) (4认同)
  • 因此,您不必检查每个查询中的删除值= 0,您可以查看为您执行此操作的表.然后,您可以创建一个名为recycle_bin或类似的视图,仅显示已删除的记录(在对其公共字段执行软删除的表上执行联合) (3认同)
  • +1使用安全,混合,两步过程 (2认同)

dev*_*xer 32

这取决于具体情况.我可以看到法律要求您真正删除某些内容的情况.也许有人要求将您的社会安全号码从您的系统中永久删除.或者您可能有一个重复记录要合并到一个记录中.使用已删除的标志保留副本可能不是有利的.

还有一个技术缺点:您无法执行级联删除操作,这会自动清除对已删除数据的任何引用以防止外键冲突.这不一定是一个大问题,但要记住这一点.

否则,我认为这是个好主意.

  • 以"它取决于..."开头的+1 (4认同)
  • 好点重新:级联删除. (2认同)
  • @UpTheCreek:我认为DanM的观点是,如果你正在进行软删除,你必须自己处理级联删除.如果您正在使用硬删除(我称之为"正常"),您可以让DB自动执行级联删除操作. (2认同)

Jos*_*ton 24

如果您要使用软删除,最好使用deleted_date字段,而不是is_deleted字段.你得到一个很好的额外数据而不仅仅是位字段.

  • 使用DateTime字段而不是Bits的+1 ...我必须使用"IsSomething"和"DateSomethinged"管理的旧系统数量非常高...... (3认同)

xan*_*ndy 20

软删除的主要问题之一是那些不需要的数据可能会影响db性能.几年前,我的一个客户端要求我对所有数据库项进行软删除,我的解决方案是将所有"已删除"项目移动到备份表,而不是将其留给当前运行的表.

  • 您可以通过"IsDeleted"对表进行分区,以便在数据库中执行此操作时降低性能影响.然后你不必担心两个不同的表. (15认同)
  • +1用于将数据移动到另一个表! (4认同)

Ant*_*ram 17

如果无效删除绝对是灾难性的,恢复应该很简单,这是一个好主意.如果你想跟踪曾经发生过的事情,这也是一个好主意,"删除"实际上只意味着"隐藏".意思是,这取决于具体情况.


rjh*_*a94 9

我不会试图"在政治上正确".如果你提倡软删除,那么你需要进行大脑检查.

1)首先,通过不删除表中的行,您究竟达到了什么目的?事实上,将来某个时候你可以访问这些行,对吧?那么为什么不创建一个存档表并在那里移动行?这有什么问题?

2)使用软删除,您将在is_active上创建不必要的查询或在某个时间戳列上创建查询.当你编写更简单的查询时,这只是浪费.是的,它可以用于视图,但是视图不是额外的附属物吗?每个视图都是一个额外的SQL,额外的性能成本,在任何商业RDBMS中都只是一个表.除了你不知道如何在表格之上编写查询这一事实之外,没有任何神奇的观点.

3)是的,它可以使用View或MV.但后来我看到生产中的查询做FTS,一切仍然有效!现代硬件和固体软件的奇迹.但那也不是正确的.因此,通过相同的逻辑,仅仅因为它起作用并不意味着它是正确的

4)软删除的复杂性永远不会停留在一个简单的选择.

A)假设您有一个UNIQUE约束.现在您软删除一行,但具有UNIQUE约束的列仍然存在.当你想要重新添加相同的数据时,如果没有额外的"技巧",你就无法做到这一点.

B)您可能有从表A到表B的关联,当您从表A中软删除某些内容时,您需要确保表B上的独立查询处理该事实.假设一个典型的详细信息页面正在处理一些detail_id.

现在,master_id被软删除,但你仍然可以在任何地方使用master_id的detail_id永久链接.在master_id上进行硬删除时,这些细节根本不存在.现在使用软删除它们仍然存在,并且它们必须知道它们的master_id处于软删除模式的事实.

它不会停留在简单的Table_A.is_active = 0或1阶段.

5)做简单而正确的删除操作.

A)没有人必须在任何地方添加任何额外的东西或担心任何事情.

  1. 您的应用程序逻辑更简单
  2. 您的数据库较小
  3. 您的查询更快

只需存档数据+相关部分,你应该很好.

  • 这是一个非常推定的答案.如果没有针对每种情况的所有细节,您如何得出结论绝对没有任何理由使用软删除?永远不要把话说绝了.它表明你缺乏想象力. (13认同)
  • 嗯,我想说在这个页面上的流行共识,表明你独自站立.这里的人们不仅记录了可能使用它的不同场景,还记录了使其有用的实用方法.如果你选择建议所有这些人都需要"大脑检查",这是你的特权,它会反映在你身上. (7认同)
  • 硬删除不是唯一的方法.在某些情况下,您无法轻易删除记录.有时我需要删除记录的引用(在另一个表中链接),即使它已被删除,这是通过软删除来完成的.移动"存档表"中的记录并不像您描述的那样简单,它不会停止从a到b的简单移动. (4认同)
  • 并且不分享您的详细信息 - 您是否在做假设?软删除不好,我支持我的陈述.分享你的情况,我会指出你的缺点. (3认同)
  • 在某种程度上,人们普遍认为,太阳绕地球而且人们因为其他原因而被焚烧.如果您真的认为软删除是一个好主意,那么您在一段时间内没有管理任何复杂的数据库.无论你想要通过软删除实现什么,都可以通过软删除以及干净的方式实现.到目前为止,人们只是抱怨*推定*但没有人提供过任何数据.软删除是*Lazy*解决应该通过归档完成的问题.如果你不需要数据,为什么数据会在这个表中徘徊? (2认同)

Dan*_*llo 8

软删除还允许您从应用程序使用的数据库帐户撤消 DELETE权限.

  • 并不是说除了人为错误之外它会有用.如果我是恶意用户并且可以访问它,我仍然可以通过`UPDATE表SET Field1 = 0,Field2 = 0,...... WHERE来"删除"它们. 1` (12认同)

jos*_*rry 5

有时软删除是必要的.例如,假设您有一个引用Products表的Invoice表.一旦您创建了具有特定产品的发票,您就可以永远不会删除该产品(如果您的RI设置正确,它将不会让您).

此特定方案假定您永远不想删除发票,在真实公司中您可能不希望删除历史财务数据.

虽然还有许多其他情况下您无法删除某些数据作为依赖关系的副作用,但由于业务或其他原因导致链条无法删除.

  • 这不是"暂停"而不是"删除"吗?因此,我认为当您需要历史数据时,"暂停"记录是合适的,当您不需要历史数据时,"删除"记录是合适的(或者可以轻松地撤消删除). (2认同)