策略一:源頭防止(約束)
1. 主鍵 / 唯一索引
-- 雙主鍵(隱含 NOT NULL)
CREATE TABLE person_tbl (
first_name CHAR(20) NOT NULL,
last_name CHAR(20) NOT NULL,
sex CHAR(10),
PRIMARY KEY (last_name, first_name)
);
-- 唯一索引(允許 NULL)
CREATE TABLE person_tbl (
first_name CHAR(20) NOT NULL,
last_name CHAR(20) NOT NULL,
sex CHAR(10),
UNIQUE (last_name, first_name)
);
2. INSERT IGNORE / REPLACE
-- 忽略重複,不報錯
INSERT IGNORE INTO person_tbl (last_name, first_name) VALUES ('Jay', 'Thomas');
-- 第 2 次執行:Query OK, 0 rows affected
-- 存在則刪除舊行再插入
REPLACE INTO person_tbl (last_name, first_name) VALUES ('Jay', 'Thomas');
策略二:統計重複數據
SELECT COUNT(*) AS repetitions, last_name, first_name
FROM person_tbl
GROUP BY last_name, first_name
HAVING repetitions > 1;
策略三:過濾重複(查詢去重)
-- DISTINCT
SELECT DISTINCT last_name, first_name FROM person_tbl ORDER BY last_name;
-- GROUP BY
SELECT last_name, first_name FROM person_tbl GROUP BY (last_name, first_name);
策略四:物理刪除重複數據
方法 1:臨時表法(通用)
CREATE TABLE tmp SELECT last_name, first_name, sex
FROM person_tbl GROUP BY (last_name, first_name);
DROP TABLE person_tbl;
ALTER TABLE tmp RENAME TO person_tbl;
方法 2:ALTER IGNORE ADD PRIMARY KEY(MySQL 5.7+ 已移除 IGNORE)
ALTER IGNORE TABLE person_tbl ADD PRIMARY KEY (last_name, first_name);
注意: MySQL 5.7+ 移除 ALTER IGNORE,請使用方法 1 或窗口函數 ROW_NUMBER() (8.0+)。
最佳實踐建議
- 設計階段即加唯一約束
- 業務層面做幂等性校驗
- 定期跑統計腳本發現異常
- 刪除前必須備份