三種標準語法
1. VALUES 子句 — 單筆/少量明確值
INSERT INTO Table1 (Id, Name, Address) VALUES (1, N'YGL', N'Beijing');
- 支援多列值:`VALUES (1,'A'), (2,'B'), (3,'C')` (SQL 2008+)。
- 適用 T-SQL / PL/SQL 通用。
2. SELECT INTO — 建立新表並複製資料 (T-SQL 專用)
SELECT Id, Name, Address INTO Table2 FROM Table1;
- 自動建立 `Table2`,結構與 SELECT 清單一致(含身分欄、NULL 屬性)。
- 不複製:索引、約束、觸發器、擴充屬性、權限。
- 最小記錄 (Minimal Logging) 條件下效能極佳(大量資料初始化首選)。
3. INSERT ... SELECT — 彈性最高、支援複雜來源
INSERT INTO Table2 (Id, Name, Address)
SELECT Id, Name, Address FROM Table1 WHERE Region = 'North';
- 可指定目標欄位順序,來源查詢任意複雜 (JOIN、UNION、函數)。
- 跨資料庫/連結伺服器同步:`INSERT INTO LocalDB.dbo.T SELECT * FROM LinkedSrv.RemoteDB.dbo.T`。
常見陷阱與避坑
| 陷阱 | 錯誤寫法 | 正確做法 |
| 省略目標欄位清單 | `INSERT INTO Table2 SELECT * FROM Table1` | 明確列出目標欄位:`INSERT INTO Table2 (Col1, Col2) SELECT Col1, Col2 FROM Table1` |
| 目標表有 NOT NULL 欄位未提供值 | `INSERT INTO Table2 (Col1) SELECT Col1 FROM Table1` (Col2 為 NOT NULL 無預設) | 在 SELECT 提供預設值:`SELECT Col1, 'Default' FROM Table1` 或目標表加預設約束 |
| 身分欄 (IDENTITY) 衝突 | 來源有明確 ID 值插入目標身分欄 | 加 `SET IDENTITY_INSERT Table2 ON` 前插入,插完 `OFF` |
| 隱含轉換失敗 | 來源 VARCHAR 插入目標 INT | 來源端 `CAST/CONVERT` 或 `TRY_CAST` (2012+) |
效能提示
- 大量資料 (萬筆以上) → `INSERT ... SELECT` + `TABLOCK` 提示 + 簡單復原模式 → 最小記錄、極速寫入。
- 頻繁小批次 → 參數化 `VALUES` + 重用命令物件 (應用層) 或 `MERGE` (Upsert)。
- `SELECT INTO` 建表後立即建立索引/約束,避免後續 `ALTER TABLE` 鎖表。