業務開發中頻繁需求:表間數據遷移、歸檔、初始化、去重同步。INSERT INTO ... SELECT單條SQL解決,避免應用層拆解循環。本文系統講解四大核心場景語法與實戰模板。
CREATE TABLE insertTest (id INT(4), name VARCHAR(12));
CREATE TABLE insertTest2 (id INT(4), name VARCHAR(12));
INSERT INTO insertTest VALUES (100,'liudehua'),(101,'zhourunfa'),(102,'zhouhuajian');
INSERT INTO 目標表 SELECT * FROM 來源表;
-- 例
INSERT INTO insertTest2 SELECT * FROM insertTest;
INSERT INTO 目標表 (欄位1, 欄位2, ...) SELECT 欄位1, 欄位2, ... FROM 來源表;
-- 例:僅複製id
INSERT INTO insertTest2 (id) SELECT id FROM insertTest;
INSERT INTO 目標表 (欄位1, 欄位2, ...)
SELECT 欄位1, 欄位2, ...
FROM 來源表 src
WHERE NOT EXISTS (
SELECT 1 FROM 目標表 dst WHERE dst.比較欄位 = src.比較欄位
);
INSERT INTO insertTest2 (id, name)
SELECT id, name FROM insertTest src
WHERE NOT EXISTS (SELECT 1 FROM insertTest2 dst WHERE dst.id = src.id);
INSERT INTO insertTest (id, name)
SELECT 100, 'liudehua' FROM dual
WHERE NOT EXISTS (SELECT 1 FROM insertTest WHERE id = 100);
注意:MySQL/Oracle支援DUAL,SQL Server用VALUES或省略FROM。
INSERT INTO target_table (col1, col2, col3)
SELECT a.col1, b.col2, c.col3
FROM table_a a
JOIN table_b b ON a.id = b.a_id
JOIN table_c c ON b.id = c.b_id
WHERE a.status = 1;
| 場景 | 建議 |
|---|---|
| 大表全量複製(>100萬行) | 分批次(LIMIT 50000 OFFSET ...),避免長事務、鎖升級、Binlog暴增 |
| 目標表有唯一索引 | 用INSERT IGNORE或ON DUPLICATE KEY UPDATE替代NOT EXISTS,效能更優 |
| 跨資料庫複製 | INSERT INTO db1.tbl SELECT * FROM db2.tbl(同實例);異構用ETL工具或FEDERATED引擎 |
| 自增主鍵衝突 | 目標表自增列不指定值,或SET @auto_inc=...調整起始值 |
| 字符集不一致 | 確保兩表CHARSET一致,或CONVERT(col USING utf8mb4) |
REPLACE INTO:唯一鍵衝突→刪除舊行→插入新行(觸發DELETE+INSERT觸發器,自增ID會變)INSERT IGNORE:衝突→忽略不報錯,保留舊行ON DUPLICATE KEY UPDATE:衝突→更新指定欄位,保留主鍵ID,最高效靈活掌握INSERT INTO SELECT全場景語法,讓表間數據流轉從「代碼堆砌」變為「SQL一條龍」。