MySQL การจัดการข้อผิดพลาดใน Stored Procedure ด้วย HANDLER

Stored Procedure ใน MySQL อาจเจอปัญหาเหมือนกับโปรแกรมทั่วไป เช่น ข้อมูลผิดพลาด, หารด้วยศูนย์, หาข้อมูลไม่เจอ หรือการ insert/update ที่ล้มเหลว หากไม่จัดการข้อผิดพลาดเหล่านี้ อาจทำให้ระบบล่ม หรือเกิดข้อมูลไม่ครบถ้วน

MySQL มีคำสั่งที่ชื่อว่า DECLARE HANDLER เพื่อใช้สำหรับ จัดการ error และควบคุม flow เมื่อเกิดเหตุการณ์ที่ไม่คาดคิด

รูปแบบการใช้งาน DECLARE HANDLER

DECLARE handler_type HANDLER
FOR condition_value
    statement;
  • handler_type เช่น CONTINUE, EXIT
  • condition_value เช่น SQLEXCEPTION, NOT FOUND, SQLSTATE '23000'
  • statement คือคำสั่งที่จะให้ทำเมื่อเกิด error

ตัวอย่างการใช้งาน

ตัวอย่างที่ 1 ป้องกันการหารด้วยศูนย์

SQL
DELIMITER //

CREATE PROCEDURE safe_divide(IN numerator INT, IN denominator INT)
BEGIN
  DECLARE result DECIMAL(10,2);
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
    SET result = NULL;

  SET result = numerator / denominator;
  SELECT result AS ผลลัพธ์;
END //

DELIMITER ;

เรียกใช้งาน

SQL
CALL safe_divide(10, 0);

ผลลัพธ์

ผลลัพธ์
NULL

ตัวอย่างที่ 2 จัดการกรณีไม่พบข้อมูล (NOT FOUND)

สมมุติว่าเรามีตาราง employees ซึ่งเก็บข้อมูลดังนี้

employee_idfull_name
1สมชาย
2อริสา

ต้องการดึงชื่อพนักงานตาม ID แต่หากไม่พบข้อมูล ก็ให้แสดงว่า “ไม่พบพนักงาน”

SQL
DELIMITER //

CREATE PROCEDURE find_employee(IN emp_id INT)
BEGIN
  DECLARE emp_name VARCHAR(100) DEFAULT 'ไม่พบพนักงาน';
  DECLARE CONTINUE HANDLER FOR NOT FOUND
    SET emp_name = 'ไม่พบพนักงาน';

  SELECT full_name INTO emp_name
  FROM employees
  WHERE employee_id = emp_id;

  SELECT emp_name AS ผลลัพธ์;
END //

DELIMITER ;

เรียกใช้งาน

SQL
CALL find_employee(99);

ผลลัพธ์

ผลลัพธ์
ไม่พบพนักงาน

ประเภทของ HANDLER

  • CONTINUE ให้รันคำสั่งถัดไปต่อแม้เกิด error
  • EXIT หยุดการทำงานของ Procedure ทันทีเมื่อเกิด error

สิ่งที่ตรวจจับได้ใน FOR

  • SQLEXCEPTION จับ error SQL ทั่วไป เช่น syntax ผิด
  • SQLWARNING จับ warning เช่น ค่าไม่ตรงชนิดข้อมูล
  • NOT FOUND ใช้กับ SELECT INTO, FETCH ไม่เจอข้อมูล
  • SQLSTATE 'xxxxxx' จับ error code เฉพาะเจาะจง

หมายเหตุ

  • ต้อง DECLARE HANDLER ก่อนคำสั่งอื่นภายใน BEGIN ... END
  • ใช้ CONTINUE อย่างระมัดระวัง เพราะจะไม่หยุด Procedure เมื่อเกิด error
  • อย่าลืมตรวจสอบ NULL ในผลลัพธ์ที่ได้จาก HANDLER ถ้าใช้กับ OUT parameter
แชร์เรื่องนี้