Để chèn nhiều bản ghi trong một câu lệnh INSERT duy nhất (batch insert), bạn liệt kê nhiều bộ giá trị trong mệnh đề VALUES, cách nhau bằng dấu phẩy.
Cú pháp
INSERT INTO ten_bang (cot1, cot2, ...)
VALUES
(gia_tri_1_1, gia_tri_1_2, ...),
(gia_tri_2_1, gia_tri_2_2, ...),
(gia_tri_3_1, gia_tri_3_2, ...),
...;
-- Hoặc bỏ danh sách cột nếu chèn đủ cột theo thứ tự
INSERT INTO ten_bang VALUES
(val1, val2), (val3, val4), ...;
Ví dụ minh họa
1. Tạo bảng
CREATE TABLE addMultipleValues (
Counter INT NOT NULL
);
2. Batch INSERT 10 hàng một lần
INSERT INTO addMultipleValues VALUES
(1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
Kết quả: Query OK, 10 rows affected (0.27 sec) Records: 10 Duplicates: 0 Warnings: 0
3. Kiểm tra dữ liệu
SELECT * FROM addMultipleValues;
Kết quả:
+---------+
| Counter |
+---------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+---------+
Ưu điểm của Batch INSERT
| Chỉ số | INSERT đơn lẻ (10 lần) | Batch INSERT (1 lần) |
|---|---|---|
| Round-trip network | 10 lần | 1 lần |
| Parsing/Optimization | 10 lần | 1 lần |
| Transaction overhead | 10 lần (autocommit) | 1 lần |
| Index update | 10 lần | 1 lần (bulk load) |
| Tổng thời gian (ví dụ) | ~500ms | ~50ms (10x nhanh hơn) |
Các biến thể
1. INSERT ... SELECT từ bảng khác
INSERT INTO bang_moi (cot1, cot2)
SELECT cot1, cot2 FROM bang_cu WHERE dieu_kien;
2. INSERT IGNORE (bỏ qua trùng khóa)
INSERT IGNORE INTO bang (id, ten) VALUES
(1, 'A'), (2, 'B'), (1, 'C'); -- id=1 trùng, bỏ qua hàng 3
3. INSERT ... ON DUPLICATE KEY UPDATE (upsert)
INSERT INTO bang (id, ten, so_lan) VALUES
(1, 'A', 1), (2, 'B', 1)
ON DUPLICATE KEY UPDATE so_lan = so_lan + 1;
4. REPLACE INTO (xóa cũ, chèn mới)
REPLACE INTO bang (id, ten) VALUES (1, 'A_moi');
⚠️ Lưu ý quan trọng
- Giới hạn packet size:
max_allowed_packet(mặc định 4MB/64MB). Batch quá lớn → chia nhỏ. - Giới hạn số hàng: Không có limit cứng, nhưng khuyến nghị < 1000-5000 hàng/lần
- Auto-commit: Mỗi INSERT là 1 transaction. Dùng
START TRANSACTION; INSERT...; COMMIT;cho atomicity - Locking: Batch INSERT khóa bảng/index lâu hơn → ảnh hưởng concurrency
- Prepared Statement: Dùng
PREPARE stmt FROM 'INSERT ... VALUES (?, ?)'; EXECUTE stmt USING @a, @b;cho an toàn SQL injection
Best Practice cho Import dữ liệu lớn
- Tắt index:
ALTER TABLE bang DISABLE KEYS;(MyISAM) hoặc drop secondary index (InnoDB) - Tắt foreign key check:
SET FOREIGN_KEY_CHECKS = 0; - Tắt unique check:
SET UNIQUE_CHECKS = 0; - Chia batch 1000-5000 rows, commit mỗi batch
- Bật lại checks/index sau khi xong
- Hoặc dùng
LOAD DATA INFILE(nhanh nhất cho file CSV/TSV)