【问题标题】:Are there problems with this 'Soft Delete' solution using EAV tables?这种使用 EAV 表的“软删除”解决方案是否存在问题?
【发布时间】:2011-03-23 16:53:57
【问题描述】:

我已经阅读了一些关于在表中设置 deleted_at 字段以表示一行已被删除的丑陋方面的信息。


http://richarddingwall.name/2009/11/20/the-trouble-with-soft-delete/

从要删除的表中取出一行并将其转入某些 EAV 表中是否存在任何潜在问题?

例如。

假设我有两个表deleteddeleted_row,分别描述如下。

    mysql> describe deleted;
    +------------+--------------+------+-----+---------+----------------+
    | Field      | Type         | Null | Key | Default | Extra          |
    +------------+--------------+------+-----+---------+----------------+
    | id         | int(11)      | NO   | PRI | NULL    | auto_increment | 
    | tablename  | varchar(255) | YES  |     | NULL    |                | 
    | deleted_at | timestamp    | YES  |     | NULL    |                | 
    +------------+--------------+------+-----+---------+----------------+

    mysql> describe deleted_rows;
    +--------+--------------+------+-----+---------+----------------+
    | Field  | Type         | Null | Key | Default | Extra          |
    +--------+--------------+------+-----+---------+----------------+
    | id     | int(11)      | NO   | PRI | NULL    | auto_increment | 
    | entity | int(11)      | YES  | MUL | NULL    |                | 
    | name   | varchar(255) | YES  |     | NULL    |                | 
    | value  | blob         | YES  |     | NULL    |                | 
    +--------+--------------+------+-----+---------+----------------+

现在,当您想从任何表中删除一行时,您可以将其从表中删除,然后将其插入到这些表中。

    deleted
    +----+-----------+---------------------+
    | id | tablename | deleted_at          |
    +----+-----------+---------------------+
    |  1 | products  | 2011-03-23 00:00:00 | 
    +----+-----------+---------------------+

    deleted_row
    +----+--------+-------------+-------------------------------+
    | id | entity | name        | value                         |
    +----+--------+-------------+-------------------------------+
    |  1 |      1 | Title       | A Great Product               | 
    |  2 |      1 | Price       | 55.00                         | 
    |  3 |      1 | Description | You guessed it... it's great. | 
    +----+--------+-------------+-------------------------------+

我看到了一些事情。

  1. 您需要使用应用程序逻辑 做支点(Ruby、PHP、Python、 等)
  2. 表可能会变得很大 因为我使用blob 来处理 行值的未知大小

您是否发现此类软删除还有其他明显问题?

【问题讨论】:

  • 我对这是否是一件好事没有太多意见(至少在没有关于您的要求的更多细节的情况下),但根据您的数据库服务器,您可能可以这样做使用触发器并将逻辑排除在数据库之外。
  • Tom,我还没有偶然发现如何使用触发器进行数据透视,你知道网上有什么好的例子吗?
  • 对不起,不是我的头顶。这也很大程度上取决于您使用的数据库。

标签: sql database-design delete-row


【解决方案1】:

为什么不用存档表来镜像您的表?

create table mytable(
   col_1 int
  ,col_2 varchar(100)
  ,col_3 date 
  ,primary key(col_1)
)

create table mytable_deleted(
   delete_id  int      not null auto_increment
  ,delete_dtm datetime not null
-- All of the original columns
  ,col_1 int
  ,col_2 varchar(100)
  ,col_3 date 
  ,index(col_1)
  ,primary key(delete_id)
)

然后简单地在您的表上添加 on-delete-triggers,在删除之前将当前行插入镜像表中?这将为您提供非常简单且非常高效的解决方案。

您实际上可以使用数据字典生成表和触发代码。

请注意,我可能不希望存档表中的原始主键 (col_1) 上有唯一索引,因为如果您使用自然键,您实际上可能会随着时间的推移两次删除同一行。除非您打算在应用程序中连接存档表(出于撤消目的),否则您可以完全删除索引。另外,我添加了删除时间 (deleted_dtm) 和一个可用于删除已删除 (hehe) 行的代理键。

您也可以考虑在 deleted_dtm 上对归档表进行范围分区。这使得从表中清除数据变得非常容易。

【讨论】:

  • 我希望避免手动创建表,但我可以看到这种方法的优点,因为它不需要任何应用程序逻辑。
  • @nvoyageur,您使用的是什么数据库?你熟悉那个 dbms 的字典表吗?您可以创建一组启用/禁用归档功能的过程或脚本,因此您不必手动创建表。是的,让数据库在后台自动执行此操作而无需自定义应用程序代码的能力非常强大!
  • MySQL 是我使用的主要数据库(在 Postgres 中有一些项目)。我对字典表没有任何经验。我要研究的东西。
  • @nvoy,谷歌搜索“information_schema”,并查看架构中数据库中同名的表。
  • @nvoy,对你有用吗?如果您发现答案对您的问题有用,请不要忘记投票和/或接受。
猜你喜欢
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 2010-11-08
  • 2020-05-17
  • 1970-01-01
相关资源
最近更新 更多