ใน MySQL สามารถสร้าง Stored Procedure หลักที่เรียก Sub-procedures หลายตัวได้ โดยใช้คำสั่ง CALL ภายใน BEGIN ... END ซึ่งช่วยจัดระเบียบ Logic ซับซ้อนและนำ Procedure ไปใช้ซ้ำได้
ไวยากรณ์พื้นฐาน
DELIMITER //
CREATE PROCEDURE main_procedure()
BEGIN
CALL sub_procedure_1();
CALL sub_procedure_2();
-- ...
CALL sub_procedure_N();
END //
DELIMITER ;
ตัวอย่างการใช้งาน
1. สร้าง Procedure แรก (แสดง Hello):
mysql> DELIMITER //
mysql> CREATE PROCEDURE hello_message()
-> BEGIN
-> SELECT 'HELLO WORLD !!';
-> END //
Query OK, 0 rows affected (0.19 sec)
2. สร้าง Procedure ที่สอง (แสดง Hi):
mysql> CREATE PROCEDURE hi_message()
-> BEGIN
-> SELECT 'HI !!!!';
-> END //
Query OK, 0 rows affected (0.11 sec)
mysql> DELIMITER ;
3. สร้าง Procedure หลักที่เรียกทั้งสอง:
mysql> DELIMITER //
mysql> CREATE PROCEDURE call_all_stored_procedure()
-> BEGIN
-> CALL hello_message();
-> CALL hi_message();
-> END //
Query OK, 0 rows affected (0.26 sec)
mysql> DELIMITER ;
4. เรียก Procedure หลัก:
mysql> CALL call_all_stored_procedure();
ผลลัพธ์ (แสดงผลจากทั้งสอง Procedure):
+----------------+ | HELLO WORLD !! | +----------------+ | HELLO WORLD !! | +----------------+ 1 row in set (0.06 sec) +---------+ | HI !!!! | +---------+ | HI !!!! | +---------+ 1 row in set (0.06 sec) Query OK, 0 rows affected (0.08 sec)
คำแนะนำสำคัญ
- DELIMITER: ต้องเปลี่ยนจาก ; เป็น // (หรืออีกอักขระ) ก่อน CREATE PROCEDURE เพื่อไม่ให้ ; ภายใน Procedure ทำให้คำสั่งจบก่อนเวลา
- Transaction: Procedure ย่อยที่ถูก CALL จะรันใน Transaction เดียวกับ Procedure หลัก (หากไม่มี COMMIT/ROLLBACK ภายใน)
- Error Handling: ใช้ DECLARE CONTINUE HANDLER หรือ SIGNAL/RESIGNAL (MySQL 5.5+) เพื่อจัดการข้อผิดพลาด
- Parameters: สามารถส่ง Parameter ไปยัง Sub-procedure ได้
การประยุกต์ใช้
- กระบวนการ ETL: Extract → Transform → Load แยกเป็น Procedure ย่อย
- รายงานหลายส่วน: Header, Detail, Footer เป็น Procedure แยกกัน
- Batch Processing: วนลูปเรียก Procedure ประมวลผลแต่ละ Batch
- Modular Programming: แยก Business Logic ออกเป็นหน่วยเล็กๆ
ข้อจำกัด
- MySQL ไม่รองรับ Return Value จาก Procedure (ใช้ OUT Parameter แทน)
- Recursive CALL ได้แต่ต้องตั้งค่า
max_sp_recursion_depth> 0 - Debugging ยากกว่า Code ทั่วไป (ใช้ SELECT Debug หรือ Stored Routine Debugger)