Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 通过软删除保持逻辑一致性,同时保留原始信息_Sql_Database Design_Soft Delete - Fatal编程技术网

Sql 通过软删除保持逻辑一致性,同时保留原始信息

Sql 通过软删除保持逻辑一致性,同时保留原始信息,sql,database-design,soft-delete,Sql,Database Design,Soft Delete,我有一个非常简单的表students,结构如下,其中主键是id。这个表是一个大约2000万行表的替身,这些表经常连接在一起 +----+----------+------------+ | id | name | dob | +----+----------+------------+ | 1 | Alice | 01/12/1989 | | 2 | Bob | 04/06/1990 | | 3 | Cuthbert | 23/01/1988 | +-

我有一个非常简单的表students,结构如下,其中主键是id。这个表是一个大约2000万行表的替身,这些表经常连接在一起

+----+----------+------------+ | id | name | dob | +----+----------+------------+ | 1 | Alice | 01/12/1989 | | 2 | Bob | 04/06/1990 | | 3 | Cuthbert | 23/01/1988 | +----+----------+------------+ 然后,每当我需要最新的信息时,请执行以下Oracle操作,但问题代表每个RDBMS:

select id, name, dob
  from ( select a.*, rank() over ( partition by id 
                                       order by created desc ) as "rank"
           from students a )
 where "rank" = 1
正面:我从不丢失任何信息

否定:整个数据库中的所有查询都需要更长的时间。如果表的大小是指定的大小,这并不重要,但一旦你在你的第五个左外连接使用范围扫描,而不是独特的扫描开始有效果

添加一个不同的列,删除日期默认为“2100/01/01”,“yyyy/mm/dd”,或者我喜欢的任何太早或未来的日期。将主键更改为id,删除,然后每次更新都变为:

获取当前信息的查询变成:

select id, name, dob
  from ( select a.*, rank() over ( partition by id 
                                       order by deleted desc ) as "rank"
           from students a )
 where "rank" = 1
正面:我从不丢失任何信息

否定:两个DML操作;我仍然必须在每个查询中使用具有额外成本的排序查询或范围扫描,而不是唯一的索引扫描

创建第二个表,如student_archive,并将每个更新更改为:

insert into student_archive select * from students where id = :id;
update students set dob = :newdob where id = :id;
正面:永远不要丢失任何信息

负片:2个DML操作;如果你想得到所有的信息,你必须使用联合或额外的左外连接

为了完整性,我们有一个非常不规范的数据结构:id、name1、dob、name2、dob2。。。等等

如果1号不是一个选项,如果我永远不想丢失任何信息,总是做一个软删除。数字5可以被安全地丢弃,因为它造成的麻烦超过了它的价值

我只剩下选项2、3和4以及随之而来的负面因素。我通常会使用选项2和可怕的150行间距很好的多个子选择连接

tl;博士,我意识到我在这不是建设性的投票,但:

什么是最佳单数!在不删除任何数据的情况下保持逻辑一致性的方法


有没有比我记录的更有效的方法?在本文中,我将高效定义为更少的DML操作和/或能够删除子查询。如果你能在回答问题时想出更好的定义,请随意。

我会坚持使用4,并做一些修改。无需从原始表中删除数据;在更新或删除原始记录之前,将旧值复制到存档表就足够了。这可以通过行级触发器轻松完成。在我看来,检索所有信息并不是一个频繁的操作,而且我认为额外的连接/联合没有任何问题。此外,您还可以定义一个视图,因此从最终用户的角度来看,所有查询都很简单。

谢谢!我将4改为插入。。。使现代化显然,我没有认真考虑这一点。
select id, name, dob
  from ( select a.*, rank() over ( partition by id 
                                       order by deleted desc ) as "rank"
           from students a )
 where "rank" = 1
insert into student_archive select * from students where id = :id;
update students set dob = :newdob where id = :id;