Oracle表无日期列,如何删除当日上传的数据?(Toad环境)
这种情况确实挺闹心的,没日期列直接过滤的话,得找其他突破口。给你几个可行的方案,你可以根据自己的实际情况选:
方案1:靠Oracle的SCN追踪插入时间
Oracle每条数据插入时都会绑定一个SCN(系统变更号),这个号和时间是对应的,咱们可以利用这点筛选当日数据:
方法A:用ORA_ROWSCN搭配日志历史表
先获取今天零点左右的SCN:
SELECT MIN(scn) AS start_of_day_scn FROM v$log_history WHERE first_time >= TRUNC(SYSDATE) AND first_time < TRUNC(SYSDATE) + 1;
然后用这个SCN过滤删除:
DELETE FROM mytable WHERE ORA_ROWSCN >= (SELECT MIN(scn) FROM v$log_history WHERE first_time >= TRUNC(SYSDATE));
⚠️ 注意:ORA_ROWSCN是数据最后一次修改的SCN,如果插入后没改过数据,这个值就是插入时的SCN。另外如果日志切换太频繁,v$log_history的精度可能不够,得调整。
方法B:闪回查询对比
如果有闪回权限的话,用闪回查询拿到今天零点时表的状态,再用MINUS找出新增数据:
-- 先确认要删的数据对不对 SELECT * FROM mytable MINUS SELECT * FROM mytable AS OF TIMESTAMP TRUNC(SYSDATE); -- 确认没问题再删除 DELETE FROM mytable WHERE (主键列1, 主键列2) IN ( SELECT 主键列1, 主键列2 FROM mytable MINUS SELECT 主键列1, 主键列2 FROM mytable AS OF TIMESTAMP TRUNC(SYSDATE) );
这个方法需要表有主键/唯一键,而且得有FLASHBACK ANY TABLE或者对象级的闪回权限。
方案2:对比上传前的备份
如果你上传数据前做过备份(比如导了CSV、建了临时表备份,或者用EXPDP导出过),那直接对比备份删新增数据最稳妥:
-- 假设备份表叫temp_mytable DELETE FROM mytable WHERE (主键列1, 主键列2) NOT IN ( SELECT 主键列1, 主键列2 FROM temp_mytable );
前提是你得有上传前的完整备份哦。
方案3:抓批量插入的特征
如果今天的数据是批量导入的,可能有一些专属特征:
比如ROWID比较连续(批量插入的ROWID通常会集中在一个范围),你可以先查出来这个范围,再删除:
-- 先找ROWID范围(可以结合其他字段特征缩小范围) SELECT MIN(ROWID), MAX(ROWID) FROM mytable WHERE /* 比如某个字段是今天上传的特有值,比如批次号之类的 */; -- 确认范围里的都是要删的数据,再执行删除 DELETE FROM mytable WHERE ROWID BETWEEN 'AAAR3uAAEAAAABSAAA' AND 'AAAR3uAAEAAAABSAAZ';
⚠️ 这个方法风险有点高,ROWID不保证绝对连续,一定要先查清楚再删!
最后提醒
不管用哪种方法,一定要先跑SELECT语句确认要删除的数据集完全正确,再执行DELETE,最好在测试环境先验证一遍,避免误删重要数据!
内容的提问来源于stack exchange,提问作者Ast




