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查询获取已删除记录的主要内容,如果未能解决你的问题,请参考以下文章