資料表出現重複資料時,刪除策略取決於「重複定義」:僅關鍵欄位重複?還是整列完全相同?本文提供三種場景的標準寫法、效能優化技巧,並澄清一個常見誤區。
SELECT col1, col2, COUNT(*)
FROM tbl
GROUP BY col1, col2
HAVING COUNT(*) > 1;
DELETE FROM tbl a
WHERE (col1, col2) IN (
SELECT col1, col2 FROM tbl
GROUP BY col1, col2 HAVING COUNT(*) > 1
);
子查詢每次執行皆需全表掃描聚合,極慢。
-- 1. 建立臨時表存放每組保留的 ROWID (最大值 = 最新)
CREATE TABLE tmp_keep AS
SELECT col1, col2, MAX(ROWID) AS keep_rid
FROM tbl
GROUP BY col1, col2;
-- 2. 刪除非保留列
DELETE FROM tbl a
WHERE a.ROWID != (
SELECT b.keep_rid FROM tmp_keep b
WHERE a.col1 = b.col1 AND a.col2 = b.col2
);
COMMIT;
-- 3. 清理
DROP TABLE tmp_keep;
DELETE FROM tbl a
WHERE a.ROWID != (
SELECT MAX(b.ROWID)
FROM tbl b
WHERE a.col1 = b.col1 AND a.col2 = b.col2
);
-- 1. 建立去重臨時表
CREATE TABLE tmp_dedup AS SELECT DISTINCT * FROM tbl;
-- 2. 清空原表 (TRUNCATE 產生極少 UNDO/REDO,比 DELETE 快)
TRUNCATE TABLE tbl;
-- 3. 資料寫回
INSERT INTO tbl SELECT * FROM tmp_dedup;
-- 4. 清理
DROP TABLE tmp_dedup;
注意:若表有主鍵/唯一索引,TRUNCATE 會重置 High Water Mark 並釋放空間,後續 INSERT 效能最佳。
網路上流傳一篇標題為「怎樣快速刪除 Oracle 資料庫」的文章,內容卻是:
regedit 刪除 HKEY_LOCAL_MACHINE\SOFTWARE\Oracle 節點Program Files\Oracle 目錄這是「卸載/移除 Oracle 軟體」,而非「刪除表內重複資料」! 請勿混淆。正規卸載請使用 Oracle Universal Installer (OUI) 或 deinstall 工具,手動刪除登錄與檔案會留下殘留物導致後續安裝失敗。
| 場景 | 核心技巧 | 避坑指南 |
|---|---|---|
| 部分欄位重複 | 臨時表存 MAX(ROWID) + 索引加速 JOIN | 勿直接用 IN 子查詢刪除大表 |
| 整列重複 | CREATE TABLE AS SELECT DISTINCT + TRUNCATE + INSERT | 若有 FK 參考,需先 DISABLE CONSTRAINT |
| 大量刪除通用 | 分批刪除 (每批 5000-10000 列) + COMMIT,避免 UNDO 爆滿/鎖升級 | 監控 V$TRANSACTION.USED_UBLK |
ROWID 較大通常代表較晚插入 (非絕對,視 ASSM/手動段空間管理而定)DBMS_ROWID.ROWID_CREATE 解析細節