sql查询获取已删除记录

Posted

技术标签:

【中文标题】sql查询获取已删除记录【英文标题】:sql query to get deleted records 【发布时间】:2012-06-19 14:21:38 【问题描述】:

您有一个表table1,其中包含id 列,即int(11), not null, auto_increment,从1 开始。

假设您有 10,000 条记录。很明显,最后一条记录的 id 是 10,000。 删除 3 条记录后,表中有 9,997 条记录,但最后一条记录 id 值仍为 10,000(如果最后一条记录未删除)。

如何显示使用 1 条 sql 查询删除了哪些记录?

谢谢。

【问题讨论】:

创建一个包含 10,000 个连续值的表作为查找表。然后从查找中选择目标表中不存在的所有记录。 (这总是比尝试动态生成丢失的 ID 更快。) 如果你的 DMBS 有类似 generate_series() 的函数(我不认为 mysql 有),你可以使用它,基于 min,max,而不是硬连线压延 table . +1 因为我通过回答它学到了一些新东西 :) 一个不错的问题 :) 【参考方案1】:

我认为最简单的方法是创建一个只有 id 的虚拟/临时表。 1-1000 然后左连接到该表。

但请务必在完成后从您的虚拟/临时表中删除“已删除”记录。否则,它们每次都会出现。

>> 编辑 您可以自行加入以确定您是否缺少 ids....

select a.id + 1 MissingIds
from <table> a
left join <table> b
  on a.id = b.id - 1
where b.id is null
  and a.id < 10000

【讨论】:

您真正需要的只是一个数字表或动态生成数字的方法 @AndriusNaruševičius 不同意。有时,有一种失败证明方法是专业的,而不是过于复杂的方法。 @AndriusNaruševičius 到底有什么不专业的?是不是太快太容易了,所以你不能向你的客户收费很多小时??? 无意粗鲁。请定义“专业”。每个解决方案对于每种情况都是独一无二的。不是说这是最好的解决方案,而是因为它不“专业”而将其驳回是不对的。忽略它,因为有更好的可扩展/可管理的解决方案......现在我们正在做饭! @samyi 改进它的一种方法可能是创建一个带有“check_deleted_timestamp”列的真实表,并在检查删除时更新这些记录 - 或在删除原始记录时使用触发器“deleted_timestamp”跨度> 【参考方案2】:

你可能会发现这个 sql 在这里很有用 http://www.sqlservercurry.com/2009/06/find-missing-identity-numbers-in-sql.html

【讨论】:

【参考方案3】:

我使用this answer 作为参考。

您可以使用以下查询来查找间隙,这实质上将为您提供已删除的记录“范围”。例如,在下面的示例中,您在最终结果中返回 2 行,其值为 2 和 3,以及 6 和 7。因此您知道 ID 为 2 到 3 的行已被删除,并且 ID 为已删除 6 到 7 行(总共删除 4 行)。

我相信这满足了您在“1 SQL 查询”中获得最终结果的要求,而且不使用中间表或虚拟表。

delimiter $$
use test
$$

create table mytable (id int not null auto_increment, name varchar(100), primary key (id));
$$

insert into mytable (name) values('a')$$
insert into mytable (name) values('b')$$
insert into mytable (name) values('c')$$
insert into mytable (name) values('d')$$
insert into mytable (name) values('e')$$
insert into mytable (name) values('f')$$
insert into mytable (name) values('g')$$
insert into mytable (name) values('h')$$


delete from mytable where id = 2$$
delete from mytable where id = 3$$
delete from mytable where id = 6$$
delete from mytable where id = 7$$


SELECT (t1.id + 1) as gap_starts_at
     , (SELECT MIN(t3.id) -1
          FROM mytable t3 
         WHERE t3.id > t1.id) as gap_ends_at
  FROM mytable t1
 WHERE NOT EXISTS (SELECT t2.id FROM mytable t2 WHERE t2.id = t1.id + 1)
HAVING gap_ends_at IS NOT NULL

输出:

gap_starts_at  gap_ends_at
2              3
6              7

【讨论】:

【参考方案4】:
DECLARE @myTestTable1 TABLE
(
id INT IDENTITY(1,1) NOT NULL
,testVal int
)

DECLARE @increment AS int = 1

WHILE (@increment <= 10000)
BEGIN
INSERT INTO @myTestTable1
VALUES (@increment)

SET @increment += 1
 END

DELETE FROM @myTestTable1 WHERE id IN (100,200,300)

--SELECT * FROM @myTestTable1

 ;WITH Missing (missnum, maxid)
 AS
 (
  SELECT 1 AS missnum, (select max(id) from @myTestTable1)
  UNION ALL
   SELECT missnum + 1, maxid FROM Missing
   WHERE missnum < maxid
   )
     SELECT missnum
     FROM Missing
     LEFT OUTER JOIN @myTestTable1 tt on tt.id = Missing.missnum
     WHERE tt.id is NULL
     OPTION (MAXRECURSION 0); 

但这需要很多时间。我们必须减少时间。

【讨论】:

【参考方案5】:

首先,我将展示生成 10.000 条记录的最简单方法。没有巨大的查询,没有变量。执行时间:~3ms。 LINK

现在关于我承诺的那个触发器。 LINK

如您所见,创建一个非常容易。请记住,触发器不仅不需要各种连接更好,而且您还可以存储日期、用户 ID 等(非常可扩展的示例)。 触发器连接的要点是:您不在乎有多少记录/现在/将有多少。您不需要严格控制大小。这就是为什么我称​​sam yi的回答不够专业。抱歉造成误会,我敢肯定我们都不想侮辱任何人。

通过创建这个示例,我确实学到了一些东西。希望你也这样做了:)

【讨论】:

sqlfiddle.com/#!2/ab17a/1 - 我已经为架构面板下方的“分隔符”命令(注意“|”)构建了一个 UI 替代方案。使用它,您可以构建基于触发器的选项。

以上是关于sql查询获取已删除记录的主要内容,如果未能解决你的问题,请参考以下文章

Netezza - 从 SQL 语句中获取已删除记录的计数

SQL查询删除表中的相关记录

sql语句 分次(多次)获取不重复记录,请高手赐教!

Db2 事务日志已锁定,无法归档

Spark SQL cassandra 删除记录

SQL Server 批量删除重复记录