將一個表 (或多表聯查) 的查詢結果直接插入到另一個表中。列名不必相同,但列順序、數量、數據類型必須一一對應兼容。
| 場景 | 語法模板 | 說明 |
|---|---|---|
| 完整複製 (結構完全一致) | 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; | 自動創建表結構並導入數據,不複製索引/約束/標識屬性 |
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 值導致邏輯錯誤;列表顯式指定,支持字段組合/計算。
-- 目標表 b 只有部分列與源表 a 對應
INSERT INTO b (col1, col2, col3, col4)
SELECT col1, col2, col3, col4
FROM a
WHERE CreateDate > '2023-01-01';
-- 完整複製結構與數據 (無索引/約束/標識)
SELECT * INTO NewTable FROM SourceTable;
-- 只導入部分列
SELECT ColA, ColB, ColC INTO NewTable FROM SourceTable WHERE ColD = 1;
-- 壞習慣
INSERT INTO Target SELECT * FROM Source;
-- 好習慣
INSERT INTO Target (Id, Name, Email, CreateTime, Status)
SELECT UserId, UserName, Email, RegDate, 1 FROM SourceUsers;
TABLOCK 提示 + 簡單/大量日志恢復模式,實現最小日志記錄:INSERT INTO Target WITH (TABLOCK) SELECT ... FROM Source;-- 需保持源表標識值時
SET IDENTITY_INSERT TargetTable ON;
INSERT INTO TargetTable (Id, ColA, ColB) SELECT Id, ColA, ColB FROM SourceTable;
SET IDENTITY_INSERT TargetTable OFF; -- 必須關閉,否則後續插入報錯
-- 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 或不插入該列讓自動生成 |