我应该删除或禁用关系数据库中的行吗?

时间:2008-12-07 03:00:38

标签: mysql sql oracle relational

在一个全新的程序中,空间并不是什么大不了的事情,最好是删除行或禁用行,让我们说布尔“禁用”并让程序忽略它?

例如,如果我想从程序中删除用户。

18 个答案:

答案 0 :(得分:22)

这取决于。 (但你已经猜到了,我确定。)

在实践中,违反正确使用的方法几乎总是朝着删除的方向发展。

删除的主要不良后果是在父记录消失时其他表中依赖记录的参与完整性丢失的频率。

用于保护删除的一个红鲱鱼(你已经通过解除存储容量问题已经妥善处理),期望它会在查询效率方面产生明显的差异。

有太多用户或软件问题导致某人需要点击“撤消”按钮的情况;如果你删除,你就不走运了(至少没有得到特别的帮助,加重了你宁愿做的人。)

我通常使用的术语是“活动”和“非活动”。


还需要考虑几点(Totophil):

  1. 删除某些数据库中的记录不会自动释放磁盘空间。
  2. 清除您不再需要的任何敏感信息有助于避免安全风险。
  3. 数据保护法规可能要求贵组织在某些情况下清除有关个人的任何可识别信息。立法因国家而异,有些指示:

  4. 另一方面,法律可能要求您保留某些信息。

答案 1 :(得分:22)

不删除会为将来的所有查询创建一个新的错误类。不要忘记查询编写通常由高级用户(即非IT专业人员)和初级开发人员完成。因此,现在每个具有仅由BIT活动标志标记的无效数据的表将在WHERE子句中为从现在起到永远的每个查询都需要一个额外的AND。这将有助于用户陷入失败的困境而不是成功的陷阱。但是,我强烈建议您无论如何都要实现这些标记系统,因为没有糟糕的设计,维护开发人员无需修复它将创建的众多错误。

表中的历史数据有多大价值?如果业务如果向前看,在表中包含旧数据可能只是一个负担 - 它在创建约束时会导致问题(必须修改所有约束以排除您希望的数据不存在)。数据质量保证变得复杂,因为必须不断重新识别什么是“我们害怕删除但又不想再次使用或更新”的旧垃圾以及我们关心的新内容。

它被删除是因为这是一个错误吗?如果行对应于现实生活中的实体,那么保持并设置“蒸发”,“死”,“离开建筑物”标志可能是有趣的。如果您不小心插入了与现实生活中没有实体相对应的行,则DELETE不是一件坏事。从未存在的想象客户是否很重要,以保留在客户表中?

最后,人格起着重要作用。人们也可以对数据进行打包。如果DBA将所有报纸保存在30年前并且不喜欢删除数据,那么他应该确保他根据优点做出数据设计决策而不是无关的个人偏好。

答案 2 :(得分:17)

在阅读了一本关于时态数据库设计的书之后,我开始相信这样一种理念,即每个时间重要性记录都需要至少有4个时间戳列。这四个是:创建,删除,开始,结束。创建和删除的时间戳相当不言自明。您的系统不应该查看之前删除的记录()。开始和结束列确定数据何时适用于您的系统。这是为了保持变化的历史。如果需要更新记录,则将其结束时间设置为now(),复制,更新副本,并将副本的开始时间设置为now()。这样,当您需要查看历史上的某种方式时,您可以让系统弄明白。您还可以将开始设置为将来的某个点,以便在此时自动进行更改,或将结束设置为将来使其自动消失的时间。将创建/删除的时间戳设置为未来并没有多大意义......

答案 3 :(得分:16)

如果您确实使用了已删除,可见,非活动等列,则可以抽象使用视图来记住使用它。

答案 4 :(得分:6)

这取决于你和你的要求(当记录存在时,某些事情会变得相当困难......)。

我会说布尔值是一个糟糕的选择。使其成为可以为空的时间戳。知道什么时候被删除是非常方便的,特别是当你删除太多而想要删除部分删除时。

答案 5 :(得分:4)

这取决于。如果它被禁用,则更容易取消删除/看到有人实际删除了记录(用于审计)。

您可能还有技术要求不删除记录。例如,如果您想通过仅发送已更改的记录来将数据库与其他用户同步,则如果实际删除了该记录,则无法执行此操作。

答案 6 :(得分:4)

如果您有时需要删除数据,但不经常需要:您可以将记录移动到单独的数据库 / table(例如usersusers_deleted,或者更好somedb.userssomedb_deleted.users)。

这样,数据仍然可以通过查询访问(虽然它不会像普通的那样简单),但它不会使原始数据库混乱,也不必围绕它进行编码。 / p>

答案 7 :(得分:4)

您需要具备功能要求。如果没有明确说明你将不得不自己解决它。

在大多数情况下,最好将这些记录存储在单独的表中。然后,您可以避免一个表引用另一个表的各种情况,并且您需要确定第二个表中的记录是否也应被视为已删除。

答案 8 :(得分:3)

向表中添加“DELETED”列并标记行而不是删除它们会为您带来更多的工作,而且几乎没有任何好处(如果有的话)。现在,每次编写查询时都必须记住包含“WHERE DELETED IS NOT NULL”(或其他)。

更好的方法是在需要删除数据时删除数据,并依靠常规备份过程来确保不会丢失任何数据。如果由于某种原因你需要保留一些删除的数据(对于搜索,可能),你最好只是将数据复制到为此目的创建的另一个表,然后删除原件。

多年来我一直在继承许多数据库,不幸的是,这种标记记录而不是删除它们的策略很常见,并且(至少在我的经验中)总是会导致重大问题。

答案 9 :(得分:2)

除非您特别需要管理自己的删除,否则最好只删除行。

答案 10 :(得分:2)

我想要注意的是(在大多数国家/地区)用例,由于法律原因您无法删除记录。当然,行业和数据依赖。

在这种情况下,我认为guidleine的最佳做法是将“已删除”数据映射到表格,这样可以获得实际删除outlined by MatthewMartin的好处,并且通过扩展,我发现这种模式经常比创建“活动”更好“我的数据表中的位标记。

答案 11 :(得分:1)

这应该由应用程序需求决定。我已经做到了两个方面。我有一些需要支持撤消的应用程序,因为删除行的成本 - 以及由此引起的级联删除 - 太昂贵而没有它。但是,通常情况下,我所做的应用程序要求用户确认删除,然后按照用户的要求进行操作。在某些情况下,由于隐私问题,您必须删除数据。也就是说,如果用户请求删除,则需要将其删除,而不是仅将其标记为不是最新的。在其他情况下(如与税务相关的交易),可能有理由将数据保持在非当前状态,直到法律不再要求为止。我的应用程序适合这两个类别。

在您需要保存“档案”数据的情况下,可以使用各种策略。根据是否需要立即可用,您可以将其推送到存档表,这些表可以保留或备份并定期清理。如果需要撤消,您可能希望将其保留在当前表中,只需通过设置标志来标记它。它实际上取决于模式的复杂性,应用程序的要求以及个人偏好。

答案 12 :(得分:0)

这是一个判断调用,但我最终在桌面上添加了“禁用”列,我之前认为我可以删除行。我会说大多数时候你更安全地添加一个禁用列。然而,对于n:n关系,这可能会变得棘手,所以这是需要考虑的事情。

答案 13 :(得分:0)

这取决于数据库的功能。它是所有真相的来源吗?如果是,则禁用而不是删除,因为它更容易从错误操作中恢复(即用户错误)。如果数据库是从某个上游数据源提供的,则删除未使用的数据。任何娱乐/恢复都可以由上游系统完成。

答案 14 :(得分:0)

最好添加“已删除”列并提供用户取消删除或清除已删除的项目。

答案 15 :(得分:0)

许多人已经说过,应用程序需要决定你想做什么。但对我来说,标记一行似乎没有使用正确的工具来做正确的事情。我们逻辑上将删除视为DELETE,因此如果由于法律原因不允许删除,则不要首先删除它。 同时,我考虑所有内部数据结构保持和索引。更不用说可以用来检索数据的所有优化,但添加该检查(在视图或查询中)会以数据库的复杂性和实体之间的关系呈指数级地影响性能。

简而言之,将删除逻辑放在UI层中以防止用户错误,并为应该能够删除它的用户授予删除权限。使用常规备份来保存存档。如果您的应用程序绝对需要严格的审计历史记录,请在触发器中实现它并将审计放在异地数据库中以避免所有流量,检查和废弃生产。

答案 16 :(得分:0)

我常用两种额外的解决方案。我同意其他发布的信息,这些信息完全取决于您的数据要求。

如果用户使用外键约束(如果您的RDBMS支持)会导致参照完整性问题,则可以阻止用户删除该记录。有几次我向最终用户提供了一条消息:“你不能删除这个< object>直到你取消关联< parent object>”。只要您没有预料到与另一个或多个其他表格的关联数量非常多,这种方法就可以正常工作。

另一种方法是将任何未关联的记录移动到与未删除的记录相关联。例如,假设您有一个课程,其中10个单独的课程时间与之相关联。如果您删除课程,则可以允许用户决定是否删除所有10个课程,或者是否与新课程或现有课程相关联。

答案 17 :(得分:0)

我正在创建一个CRUD,我面临同样的问题。

解决方案:CRUD的D应该禁用而不是删除。

问题:

  • “每个”查询应检查注册表是否已禁用(例如,flag = 1)。更具体地说,选择*应该检查。
  • 默认情况下,每个插入都应激活注册表(flag = 1)。
  • 更新不应更改标志。
  • 禁用是伪装的更新,标记为flag = 0。

大问题

  • 垃圾收集器。存在三种策略:删除旧注册表,删除未引用的注册表或混合策略。