การ INSERT หลายแถวพร้อมกันด้วยคำสั่งเดียว (Multi-row INSERT)
MySQL รองรับการแทรกหลายแถวในคำสั่ง INSERT เดียว โดยคั่นชุดค่าด้วยคอมมา — เร็วกว่าและ atomic กว่า INSERT หลายคำสั่ง
สร้างตาราง
mysql> create table DemoTable1384 (
-> StudentId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> StudentName varchar(20),
-> StudentAge int
-> );
Query OK, 0 rows affected (0.63 sec)
คำสั่ง INSERT หลายแถว
mysql> insert into DemoTable1384(StudentName, StudentAge) values
-> ('Chris Brown', 21),
-> ('David Miller', 22),
-> ('Carol Taylor', 19),
-> ('Adam Smith', 23);
Query OK, 4 rows affected (0.11 sec)
Records: 4 Duplicates: 0 Warnings: 0
ข้อมูลหลัง INSERT
+-----------+--------------+------------+ | StudentId | StudentName | StudentAge | +-----------+--------------+------------+ | 1 | Chris Brown | 21 | | 2 | David Miller | 22 | | 3 | Carol Taylor | 19 | | 4 | Adam Smith | 23 | +-----------+--------------+------------+
ข้อดีของ Multi-row INSERT
- ประสิทธิภาพ: ส่งคำสั่งเดียว ลด network round-trip, parsing, optimization overhead
- Atomicity: ใน transaction เดียว — สำเร็จทั้งหมดหรือล้มเหลวทั้งหมด
- Auto-increment: ให้ ID ต่อเนื่องกันโดยไม่มีช่องว่าง
ข้อจำกัด
max_allowed_packet— ขนาด packet สูงสุด (default 4MB/64MB) หากข้อมูลใหญ่เกิน ต้องแบ่ง batch- จำนวนค่าในแต่ละ tuple ต้องเท่ากันทุก tuple
- ไม่สามารถใช้
ON DUPLICATE KEY UPDATEกับคอลัมน์ auto-increment ได้อย่างมีความหมาย (จะใช้ค่า LAST_INSERT_ID() ของแถวแรก)
แนวทางปฏิบัติที่ดี (Best Practices)
- Batch size: 100-1000 แถวต่อคำสั่ง (ขึ้นอยู่กับขนาดแถว)
- Transaction: ห่อด้วย
START TRANSACTION; ... COMMIT;สำหรับ batch ใหญ่ - Prepared statements: ใช้ parameterized query ป้องกัน SQL injection
- LOAD DATA INFILE: สำหรับข้อมูลปริมาณมาก (bulk load) เร็วกว่า INSERT มาก
ตัวอย่าง Prepared Statement (ภาษา Go)
stmt, _ := db.Prepare("INSERT INTO users(name, age) VALUES (?, ?)")
for _, u := range users {
stmt.Exec(u.Name, u.Age)
}