首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL 跨表數據插入完全指南:INSERT INTO SELECT 多場景實戰

     編輯:關於SqlServer

核心語法:INSERT INTO ... SELECT ...

將一個表 (或多表聯查) 的查詢結果直接插入到另一個表中。列名不必相同,但列順序、數量、數據類型必須一一對應兼容。

基礎場景對照表

場景語法模板說明
完整複製 (結構完全一致)INSERT INTO TargetTable SELECT * FROM SourceTable;要求兩表結構完全相同 (列順序、類型、數量)
指定列複製 (結構部分相同/順序不同)INSERT INTO Target (ColA, ColB, ColC) SELECT ColX, ColY, ColZ FROM Source;推薦寫法,明確列映射,避免結構變更導致錯誤
帶條件篩選INSERT INTO Target (ColA, ColB) SELECT ColX, ColY FROM Source WHERE Status = 1;只遷移符合條件的數據
多表聯查插入INSERT INTO Target (A,B,C) SELECT t1.A, t2.B, t1.C FROM T1 JOIN T2 ON ...;聚合多表數據後插入
目標表不存在 (創建+導入)SELECT ColA, ColB INTO NewTable FROM SourceTable;自動創建表結構並導入數據,不複製索引/約束/標識屬性

實戰案例解析

案例 1:條件同步 - 將「台帳表」中不存在於「計量點表」的記錄同步過去

INSERT INTO MetricPoints (MeterID, MetricPointName, [Description], DepartmentID, MediumID)
SELECT 
    m.MeterID,
    m.MetricItems + m.InstallPlace AS MetricPointName,  -- 組合字段
    m.MetricItems,
    m.DepartmentID,
    m.MediumID
FROM Meters m
WHERE NOT EXISTS (
    SELECT 1 FROM MetricPoints mp WHERE mp.MeterID = m.MeterID
)
AND m.MediumID = 2;  -- 只同步特定介質

技巧點:使用 NOT EXISTS 而非 NOT IN,避免 NULL 值導致邏輯錯誤;列表顯式指定,支持字段組合/計算。

案例 2:結構不完全一致的表間遷移

-- 目標表 b 只有部分列與源表 a 對應
INSERT INTO b (col1, col2, col3, col4)
SELECT col1, col2, col3, col4
FROM a
WHERE CreateDate > '2023-01-01';

案例 3:創建新表並導入數據 (SELECT INTO)

-- 完整複製結構與數據 (無索引/約束/標識)
SELECT * INTO NewTable FROM SourceTable;

-- 只導入部分列
SELECT ColA, ColB, ColC INTO NewTable FROM SourceTable WHERE ColD = 1;
⚠ SELECT INTO 限制:
  • 新表無主鍵、索引、外鍵、默認值、檢查約束、標識列屬性 (需手動補充)。
  • 事務日志記錄較多 (簡單恢復模式下可最小化)。
  • 並發下可能阻塞系統表,大表慎用生產環境核心時段。

高級技巧與最佳實踐

1. 顯式列出所有列 (防範結構變更)

-- 壞習慣
INSERT INTO Target SELECT * FROM Source;

-- 好習慣
INSERT INTO Target (Id, Name, Email, CreateTime, Status)
SELECT UserId, UserName, Email, RegDate, 1 FROM SourceUsers;

2. 大批量插入性能優化

  • 分批提交:大數據量 (10萬+) 分批 5000-10000 條提交,避免事務日志暴漲、鎖升級、tempdb 壓力。
  • 最小化日志:配合 TABLOCK 提示 + 簡單/大量日志恢復模式,實現最小日志記錄:
    INSERT INTO Target WITH (TABLOCK) SELECT ... FROM Source;
  • 禁用非必要索引/約束:導入前禁用目標表非聚集索引、外鍵,導入後重建/啟用。
  • 排序輸入:若目標表有聚集索引,按聚集鍵順序 SELECT,減少頁分裂。

3. 身份列 (IDENTITY) 保持處理

-- 需保持源表標識值時
SET IDENTITY_INSERT TargetTable ON;
INSERT INTO TargetTable (Id, ColA, ColB) SELECT Id, ColA, ColB FROM SourceTable;
SET IDENTITY_INSERT TargetTable OFF;  -- 必須關閉,否則後續插入報錯

4. 避免重複插入 (Upsert 模式)

-- MERGE 語法 (SQL 2008+)
MERGE INTO TargetTable AS T
USING SourceTable AS S ON T.Id = S.Id
WHEN NOT MATCHED THEN
    INSERT (Id, ColA, ColB) VALUES (S.Id, S.ColA, S.ColB);

常見錯誤與排查

錯誤現象典型原因解決方案
列數/類型不匹配SELECT 列順序/數量與 INSERT 列表不一致雙方顯式列出列名,逐一對應檢查
字符串截斷源列長度 > 目標列長度擴大目標列長度,或 LEFT/CAST 截斷源數據
主鍵/唯一鍵衝突源數據含重複鍵值源端去重 (ROW_NUMBER/DISTINCT) 或用 MERGE/INSERT IGNORE
外鍵違規源數據引用的主表記錄不存在先同步主表,或暫時禁用外鍵
標識列插入失敗目標表有 IDENTITY,未開啟 IDENTITY_INSERT開啟 IDENTITY_INSERT 或不插入該列讓自動生成
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved