删除数据相关
大表数据清理
分批删除(Batch Delete) —— 最常用、最安全
原理: 每次只删一小部分(如 1000~10000 行),提交事务,释放资源。
示例代码(PL/SQL):
oracle
DECLARE
v_batch_size NUMBER := 5000; -- 每批删除行数
v_deleted_rows NUMBER := 1;
BEGIN
WHILE v_deleted_rows > 0
LOOP
DELETE
FROM your_big_table
WHERE create_time < DATE '2020-01-01'
AND ROWNUM <= v_batch_size;
v_deleted_rows := SQL%ROWCOUNT;
COMMIT; -- 每批提交,释放 UNDO
DBMS_LOCK.SLEEP(1); -- 可选:休眠1秒,减少系统压力
END LOOP;
END;
/优点:
- 不会撑爆 UNDO
- 可随时中断(Ctrl+C)
- 对业务影响小(短事务)
注意事项:
- WHERE 条件必须能高效走索引(否则全表扫描每批都慢)
- 建议在业务低峰期执行
- 监控 UNDO 表空间使用率:SELECT * FROM v$undostat;
oracle数据delete误删怎么恢复
方法1:已 COMMIT?用 Flashback Query(闪回查询) 恢复(最常用)
已提交,但仍在 UNDO 保留期内(可通过闪回查询恢复)
Oracle 的 UNDO 表空间会保留历史数据一段时间(由 UNDO_RETENTION 参数控制,默认 15 分钟~数小时,DBA 可调大至数天)。
TIP
步骤
1.验证能否查到删除前的数据
sql
-- 假设你在 10 分钟前误删了数据
SELECT COUNT(*)
FROM your_table AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE)
WHERE...; -- 可加上原 DELETE 的 WHERE 条件如果返回 > 0,说明数据还在 UNDO 中,可以恢复!
2.将历史数据重新插入(推荐方式)
oracle
INSERT INTO your_table
SELECT *
FROM your_table
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE)
WHERE rowid IN (SELECT rowid
FROM your_table
AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE)
MINUS
SELECT rowid
FROM your_table -- 当前表中已不存在的行
);
COMMIT;注意:
如果表有主键/唯一约束,确保不会重复插入; 更安全做法:先导出到临时表,人工核对后再插入。
✅ 简化版(整表误删):
oracle
-- 1. 创建恢复用临时表
CREATE TABLE your_table_recover AS
SELECT *
FROM your_table AS OF TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE);
-- 2. 清空当前错误表(可选)
DELETE
FROM your_table;
-- 3. 恢复数据
INSERT INTO your_table
SELECT *
FROM your_table_recover;
COMMIT;
-- 4. 删除临时表
DROP TABLE your_table_recover;方法2:使用 FLASHBACK TABLE(需提前开启行移动)
如果表开启了 行移动(Row Movement),可一键闪回整张表:
oracle
-- 先启用行移动(如果未开启)
ALTER TABLE your_table
ENABLE ROW MOVEMENT;
-- 闪回到 10 分钟前
FLASHBACK TABLE your_table TO TIMESTAMP (SYSTIMESTAMP - INTERVAL '10' MINUTE);✅ 优点:操作简单,无需写 INSERT。
❌ 缺点:会覆盖这段时间内的所有变更(不只是 DELETE,还包括其他 UPDATE/INSERT)。
