核心語法對照
| 場景 | 語法 | 特點 |
| 新表不存在,複製結構+資料 | CREATE TABLE new_tbl SELECT * FROM old_tbl; | 不複製 PK、AI、索引 |
| 新表不存在,僅複製結構 | CREATE TABLE new_tbl LIKE old_tbl; | 完整保留索引、約束、引擎 |
| 新表存在,結構相同 | INSERT INTO new_tbl SELECT * FROM old_tbl; | 需目標表已建好 |
| 新表存在,結構不同 | INSERT INTO new_tbl(c1,c2) SELECT c1,c2 FROM old_tbl; | 欄位順序、型別需對應 |
實戰範例
場景 1:建立測試環境資料子集
-- 僅複製結構
CREATE TABLE test_subset LIKE production_table;
-- 複製近 30 天資料
INSERT INTO test_subset
SELECT * FROM production_table
WHERE create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY);
場景 2:歷史資料歸檔
-- 建立歸檔表(含索引)
CREATE TABLE orders_archive_2023 LIKE orders;
-- 批次搬移,避免長事務鎖表
INSERT INTO orders_archive_2023
SELECT * FROM orders
WHERE order_date < '2024-01-01'
LIMIT 10000; -- 分批執行
常見陷阱與注意事項
- 自增主鍵衝突:目標表若有資料,來源自增 ID 可能重複 → 方案:目標表不指定 ID、或使用
REPLACE INTO、或重新產生 ID
- 大量資料複製:單次
INSERT ... SELECT 可能導致 Binlog 膨脹、鎖升級 → 分批次(如 5000-10000 行/批)、低峰期執行
- 字符集不一致:來源/目標表字符集不同會導致亂碼 → 統一使用
utf8mb4
進階技巧
-- 條件複製 + 欄位轉換
INSERT INTO user_summary (user_id, name, level, created_at)
SELECT id, CONCAT(first_name, ' ', last_name),
CASE WHEN points > 1000 THEN 'VIP' ELSE 'NORMAL' END,
FROM_UNIXTIME(reg_timestamp)
FROM users
WHERE status = 1;