數據操作語言(DML)是業務邏輯落地的核心。MySQL 在標準 SQL 基礎上擴展了 REPLACE、INSERT ... SET、多行 VALUES、DELETE ... ORDER BY/LIMIT 等實用語法。本文系統梳理五大 DML 語句的語法變體、行為差異、性能特徵與最佳實踐。
INSERT INTO users (id, name, age) VALUES (123, '姚明', 25);
INSERT INTO users SET id = 123, name = '姚明', age = 25;
INSERT INTO users VALUES (123, '姚明', 25); -- 必須給所有欄位按建表順序賦值
INSERT INTO users () VALUES (); -- 全部用默認值
INSERT INTO users (name) VALUES ('姚明'); -- 僅指定部分欄位
INSERT INTO users (name, age) VALUES
('姚明', 25),
('比爾·蓋茨', 50),
('火星人', 600);
(...) 包裹,行間用逗號分隔VALUES (1,2,3,4,5) → 視為單行 5 個欄位REPLACE = DELETE(若唯一鍵衝突)+ INSERT。語法與 INSERT 幾乎相同。
-- 用戶資料同步:以 phone 為唯一鍵,新數據覆蓋舊數據
REPLACE INTO users (phone, name, avatar, updated_at)
VALUES ('13800001111', '新名稱', 'new.jpg', NOW());
| 特性 | REPLACE | INSERT ... ON DUPLICATE KEY UPDATE |
|---|---|---|
| 衝突處理 | 刪舊插新(所有列重寫) | 就地更新指定列 |
| 自增 ID | 變化(新行新 ID) | 保持不變 |
| 外鍵關聯 | 觸發 ON DELETE CASCADE | 不觸發 |
| 性能 | 較慢(兩次操作) | 較快(單次操作) |
| 推薦度 | 低(特定場景) | 高(通用首選) |
建議:優先使用 INSERT ... ON DUPLICATE KEY UPDATE,僅在需要「完全替換行」且無外鍵依賴時用 REPLACE。
UPDATE users SET age = 24, name = 'Mike' WHERE id = 123;
TIMESTAMP 欄位若未顯式賦值,自動更新為當前時間UPDATE orders o JOIN users u ON o.user_id = u.id
SET o.status = 'shipped' WHERE u.vip_level > 2;
| 特性 | DELETE | TRUNCATE TABLE |
|---|---|---|
| WHERE 條件 | 支持 | 不支持(全表) |
| 返回影響行數 | 實際刪除行數 | 0(不返回) |
| 自增計數器 | 保持(除非 WHERE 1) | 重置為 1 |
| 觸發器 | 觸發 FOR EACH ROW | 不觸發 |
| 事務安全 | 支持回滾 | 隱式提交,不可回滾 |
| 鎖機制 | 行鎖(InnoDB) | 表鎖(元數據鎖) |
| 速度 | 慢(逐行標記) | 極快(重建表) |
| ORDER BY / LIMIT | 支持(MySQL 擴展) | 不支持 |
-- 保留自增值:永真條件掃描全表(慢但保留 ID)
DELETE FROM t1 WHERE 1;
-- 分頁刪除大表歷史數據(避免長事務鎖表)
DELETE FROM logs WHERE created_at < '2023-01-01' ORDER BY id LIMIT 10000;
-- 循環執行直到影響行數為 0
INSERT ... VALUES (...),(...),(...),單次 1000-5000 行平衡 SQL 長度與性能INSERT ... ON DUPLICATE KEY UPDATESELECT 驗證影響範圍LIMIT 10000 循環),避免長事務、複製延遲、Undo Log 膨脹TRUNCATE,但確認無外鍵依賴、無觸發器、可接受自增重置