MySQL อนุญาตให้เราสามารถ เข้าถึงค่าของข้อมูล “ก่อน” และ “หลัง” การเปลี่ยนแปลง ภายใน Trigger ได้ผ่าน keyword พิเศษดังนี้
NEW.column_nameค่าที่จะถูกบันทึก (ใช้กับINSERT,UPDATE)OLD.column_nameค่าก่อนการเปลี่ยนแปลง (ใช้กับUPDATE,DELETE)
ตารางสรุปการใช้ OLD และ NEW กับแต่ละ Trigger
| Trigger Type | ใช้ OLD ได้หรือไม่ |
ใช้ NEW ได้หรือไม่ |
|---|---|---|
| BEFORE INSERT | ❌ | ✅ |
| AFTER INSERT | ❌ | ✅ |
| BEFORE UPDATE | ✅ | ✅ |
| AFTER UPDATE | ✅ | ✅ |
| BEFORE DELETE | ✅ | ❌ |
| AFTER DELETE | ✅ | ❌ |
ตัวอย่างการใช้งาน
ใช้ NEW ใน BEFORE INSERT ตั้งค่า default ให้ช่องว่าง
เป้าหมายของตัวอย่างนี้คือ ถ้าไม่ได้กรอกอีเมล ให้ใส่ “[email protected]” แทนโดยอัตโนมัติ
Trigger
DELIMITER //
CREATE TRIGGER before_user_insert_email
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
-- ถ้าไม่ได้กรอกอีเมล ให้ตั้งค่า default
IF NEW.email IS NULL OR NEW.email = '' THEN
SET NEW.email = '[email protected]';
END IF;
END //
DELIMITER ;ใช้ OLD และ NEW ใน AFTER UPDATE บันทึกการเปลี่ยนชื่อ
เป้าหมายของตัวอย่างนี้คือ เมื่อลูกค้าเปลี่ยนชื่อ ให้บันทึก log แสดงชื่อเก่าและชื่อใหม่
Trigger
DELIMITER //
CREATE TRIGGER after_customer_update
AFTER UPDATE ON customers
FOR EACH ROW
BEGIN
-- ถ้าชื่อมีการเปลี่ยนแปลง
IF OLD.name <> NEW.name THEN
INSERT INTO customer_log(message, log_time)
VALUES (
CONCAT('เปลี่ยนชื่อจาก "', OLD.name, '" เป็น "', NEW.name, '"'),
NOW()
);
END IF;
END //
DELIMITER ;ทดสอบเปลี่ยนชื่อ
UPDATE customers
SET name = 'สมปอง'
WHERE id = 1;เมื่อมีการเปลี่ยนแปลงข้อมูล ในตัวอย่างคือการเปลี่ยนชื่อ Trigger ที่เราสร้างไว้จะทำการบันทึกการเปลี่ยนแปลงตามที่กำหนด ดังตัวอย่าง
| id | message | log_time |
|---|---|---|
| 1 | เปลี่ยนชื่อจาก “สมชาย” เป็น “สมปอง” | 2024-04-12 15:30:00 |
ใช้ OLD ใน BEFORE DELETE ย้ายข้อมูลก่อนลบ
เป้าหมายของตัวอย่างนี้คือ เมื่อลบลูกค้า ให้บันทึกชื่อไว้ในตาราง deleted_customers ก่อน
Trigger
DELIMITER //
CREATE TRIGGER before_customer_delete
BEFORE DELETE ON customers
FOR EACH ROW
BEGIN
-- บันทึกชื่อผู้ที่ถูกลบลงในอีกตาราง
INSERT INTO deleted_customers(name, deleted_at)
VALUES (OLD.name, NOW());
END //
DELIMITER ;บันทึกการอัปเดตข้อมูลลูกค้าทุกครั้ง
เป้าหมายของตัวอย่างนี้คือ ทุกครั้งที่มีการอัปเดตข้อมูลในตาราง customers ให้ระบบบันทึกค่าก่อนเปลี่ยนแปลง, ค่าหลังเปลี่ยนแปลง, และเวลาที่เปลี่ยน ลงในตาราง customer_audit_log
Trigger
DELIMITER //
CREATE TRIGGER after_customer_update_audit
AFTER UPDATE ON customers
FOR EACH ROW
BEGIN
-- ตรวจสอบการเปลี่ยนแปลงชื่อ
IF OLD.name <> NEW.name THEN
INSERT INTO customer_audit_log(field_name, old_value, new_value, log_time)
VALUES ('name', OLD.name, NEW.name, NOW());
END IF;
-- ตรวจสอบการเปลี่ยนแปลงอีเมล
IF OLD.email <> NEW.email THEN
INSERT INTO customer_audit_log(field_name, old_value, new_value, log_time)
VALUES ('email', OLD.email, NEW.email, NOW());
END IF;
END //
DELIMITER ;ทดสอบอัปเดตข้อมูล
UPDATE customers
SET name = 'สมปอง',
email = '[email protected]'
WHERE id = 1;เมื่อมีการอัปเดตข้อมูล Trigger ที่เราสร้างไว้จะทำการบันทึกการเปลี่ยนแปลงตามที่เรากำหนด ดังตัวอย่าง
| id | field_name | old_value | new_value | log_time |
|---|---|---|---|---|
| 1 | name | สมชาย | สมปอง | 2024-04-12 16:15:00 |
| 2 | [email protected] | [email protected] | 2024-04-12 16:15:00 |
ข้อควรระวังในการใช้ OLD / NEW
- ต้องใช้คู่กับ
FOR EACH ROWเท่านั้น - ห้ามใช้
SET OLD.column = ...(เปลี่ยนค่าใน OLD ไม่ได้) NEWใช้ได้เฉพาะกับ INSERT/UPDATEOLDใช้ได้เฉพาะกับ UPDATE/DELETE