Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

MySQL: เพิ่มหลายแถวในคำสั่ง INSERT เดียว

การ 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)

  1. Batch size: 100-1000 แถวต่อคำสั่ง (ขึ้นอยู่กับขนาดแถว)
  2. Transaction: ห่อด้วย START TRANSACTION; ... COMMIT; สำหรับ batch ใหญ่
  3. Prepared statements: ใช้ parameterized query ป้องกัน SQL injection
  4. LOAD DATA INFILE: สำหรับข้อมูลปริมาณมาก (bulk load) เร็วกว่า INSERT มาก
  5. ตัวอย่าง Prepared Statement (ภาษา Go)

    stmt, _ := db.Prepare("INSERT INTO users(name, age) VALUES (?, ?)")
    for _, u := range users {
        stmt.Exec(u.Name, u.Age)
    }