首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

SQL Server 刪除完全重複記錄保留首條:SELECT INTO 臨時表去重法

     編輯:MySQL 資料庫相關知識

遇到表中存在完全一模一樣的重複行(無主鍵、無唯一約束),需刪除重複僅保留第一條。本文提供經典 SELECT INTO #Temp 去重方案,並說明 SELECT INTO 權限開啟方法。

標準去重腳本

-- 1. 將去重後數據導入臨時表
SELECT DISTINCT * INTO #TmpTable FROM SourceTable;

-- 2. 清空原表
DELETE FROM SourceTable;

-- 3. 將去重數據寫回原表
SELECT * INTO SourceTable FROM #TmpTable;

-- 4. 刪除臨時表
DROP TABLE #TmpTable;

關鍵前置條件:啟用 SELECT INTO

SQL Server 默認關閉 SELECT INTO,執行上述腳本會報錯。兩種開啟方式:

方式一:企業管理器圖形化

  1. 右鍵資料庫 → 「屬性」 → 「選項」頁籤。
  2. 勾選「允許 SELECT INTO/大容量複製」。
  3. 確定,無需重啟服務。

方式二:T-SQL 命令(推薦腳本化)

EXEC sp_dboption 'DatabaseName', 'select into', 'true';

執行後立即生效,無需重啟。

進階場景:保留特定業務邏輯的「首條」

若「首條」定義為按某字段排序第一條(如最早創建時間),而非物理存儲順序:

;WITH CTE AS (
    SELECT *, 
           ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3 ORDER BY CreateTime ASC) AS RN
    FROM SourceTable
)
DELETE FROM SourceTable
WHERE EXISTS (
    SELECT 1 FROM CTE 
    WHERE CTE.Col1 = SourceTable.Col1 
      AND CTE.Col2 = SourceTable.Col2 
      AND CTE.Col3 = SourceTable.Col3 
      AND CTE.RN > 1
);
  • PARTITION BY 列出構成「重複」判定的所有業務列。
  • ORDER BY 定義保留哪一條(如最早/最新/ID 最小)。
  • 適用於 SQL Server 2005+,無需臨時表,單語句原子操作。

性能與鎖定提示

大表分批刪除模板(避免日誌爆漲、長時間鎖表)

DECLARE @BatchSize INT = 5000, @RowCount INT = 1;
WHILE @RowCount > 0
BEGIN
    DELETE TOP (@BatchSize) FROM SourceTable
    WHERE EXISTS (
        SELECT 1 FROM (
            SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1,Col2,Col3 ORDER BY ID) AS RN
            FROM SourceTable
        ) T WHERE T.RN > 1 AND T.ID = SourceTable.ID
    );
    SET @RowCount = @@ROWCOUNT;
    WAITFOR DELAY '00:00:00.100';  -- 釋放鎖喘息
    CHECKPOINT;  -- 簡單恢復模式下截斷日誌
END

總結

「完全重複行去重」核心在於 DISTINCT 投影 + 物理重建。現代環境首選 ROW_NUMBER() 窗口函數單語句解決,兼具性能、並發與語義精確性。老版本或臨時一次性任務可用 SELECT INTO #Temp,但記得先 sp_dboption 'select into', 'true'。生產大表務必分批、監控日誌空間、預留回滾方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案適用數據量鎖定行為優點缺點
SELECT INTO #Temp≤ 100 萬行Sch-M 鎖(DDL),阻塞所有訪問簡單、兼容老版本大表鎖表久、需啟用選項
ROW_NUMBER() CTE DELETE任意(配合批次)行級鎖(X),並發友好無 DDL 鎖、可保留業務首條、現代語法需 2005+、大表建議分批提交
MERGE + WHEN NOT MATCHED大表增量去重行級鎖可同步源目標、支持 UPSERT語法複雜、需目標表有鍵