游標逐行比對刪除重複記錄在百萬級數據下耗時數小時,不可接受。利用唯一索引忽略重複鍵特性,配合臨時表,僅需四條語句即可秒級完成去重。本文提供標準化操作流程與關鍵注意事項。
創建帶 IGNORE_DUP_KEY = ON 的唯一索引,批量插入源表數據時,重複鍵行會被靜默忽略(僅產生告警訊息「已忽略重複的鍵」),不報錯、不回滾,最終得到無重複的臨時表,再覆蓋回源表。
-- 1. 建立結構相同的臨時表
CREATE TABLE Products_temp (
ProductID INT,
ProductName NVARCHAR(40),
Unit CHAR(2),
UnitPrice MONEY
);
-- 2. 加唯一索引,忽略重複鍵(關鍵步驟)
CREATE UNIQUE INDEX UX_Products_temp_Dedup
ON Products_temp (ProductName, Unit, UnitPrice) -- 按業務鍵去重
WITH (IGNORE_DUP_KEY = ON);
-- 3. 批量複製數據,重複行自動過濾
INSERT INTO Products_temp SELECT * FROM Products;
-- 訊息:已忽略重複的鍵。
-- 4. 覆蓋回源表
TRUNCATE TABLE Products; -- 比 DELETE 更快、不記錄日誌
INSERT INTO Products SELECT * FROM Products_temp;
DROP TABLE Products_temp;
(ProductName, Unit, UnitPrice)。ProductID(主鍵/身份列),則每行必然唯一,去重失效。| 方法 | 耗時 | 日誌量 | 備註 |
|---|---|---|---|
| 游標循環刪除 | 數小時 | 極大 | 逐行操作、大量鎖、日誌暴增 |
| CTE + ROW_NUMBER() 刪除 | 數分鐘 | 大 | 需排序、Tempdb 壓力大 |
| 唯一索引法 | 秒級 | 極小 | 批量操作、最小日誌、無排序 |
ALTER TABLE ... NOCHECK CONSTRAINT ALL)與觸發器,完畢重啟。IGNORE_DUP_KEY 限制:僅對唯一索引生效,主鍵/非唯一索引不支援;不適用於記憶體優化表。若需保留最早/最晚插入的記錄(而非隨機保留),先按業務鍵 + 時間排序插入臨時表:
INSERT INTO Products_temp
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY ProductName, Unit, UnitPrice ORDER BY CreateTime) AS rn
FROM Products
) t WHERE rn = 1;
再按上述流程覆蓋回源表。