🗄️ MySQL/MariaDB

เข้าใจ MySQL และ MariaDB Trigger: เขียนคำสั่งอัตโนมัติให้ฐานข้อมูลทำงานแทนเรา

8 นาที 22 views บันทึกเป็น PDF
เข้าใจ MySQL และ MariaDB Trigger: เขียนคำสั่งอัตโนมัติให้ฐานข้อมูลทำงานแทนเรา

อยากให้ฐานข้อมูลทำงานอัตโนมัติเมื่อมีการเพิ่มหรือลบข้อมูลไหม? มาเรียนรู้การใช้ Trigger (ตัวกระตุ้นการทำงาน) ใน MySQL และ MariaDB เพื่อลดภาระงานโค้ดกัน

Trigger คืออะไรและทำไมต้องรู้จัก

เวลาเราเขียนโปรแกรมจัดการฐานข้อมูล บางครั้งเราอยากให้ระบบทำงานบางอย่างเองโดยอัตโนมัติเมื่อเกิดเหตุการณ์บางอย่างขึ้น เช่น เมื่อมีการเพิ่มข้อมูลลูกค้าใหม่ เราก็อยากให้ระบบส่งอีเมลแจ้งเตือนทันที ซึ่งเครื่องมือที่ช่วยจัดการเรื่องนี้ใน MySQL หรือ MariaDB ก็คือ Trigger (ตัวกระตุ้นการทำงานอัตโนมัติ) นั่นเอง

ลองนึกภาพว่าคุณมีพนักงานคอยเฝ้าหน้าประตูร้าน ถ้ามีลูกค้าเดินเข้ามา (เหตุการณ์) พนักงานคนนี้จะทำหน้าที่กล่าวต้อนรับทันที (การทำงานอัตโนมัติ) โดยที่คุณไม่ต้องไปกดปุ่มสั่งงานเองทุกครั้ง Trigger ก็ทำหน้าที่เป็นพนักงานเฝ้าฐานข้อมูลแบบนั้นเลย มันจะคอยเฝ้าคำสั่งที่คุณกำหนดไว้แล้วลงมือทำตามขั้นตอนที่วางไว้ทันที

การรู้จักใช้สิ่งนี้จะช่วยลดภาระงานของโค้ดในฝั่งโปรแกรมเมอร์ได้มาก เพราะเราไม่ต้องเขียนฟังก์ชัน (ชุดคำสั่งที่ทำงานเฉพาะอย่าง) ซ้ำซ้อนในทุกจุดที่ใช้งานฐานข้อมูล แถมยังช่วยป้องกันความผิดพลาดที่อาจเกิดขึ้นหากเราลืมเขียนโค้ดสั่งงานในบางจุด การมี Trigger ช่วยดูแลเรื่องความถูกต้องของข้อมูลจึงเป็นวิธีที่โปรแกรมเมอร์มืออาชีพเลือกใช้

ความแตกต่างของช่วงเวลา BEFORE และ AFTER

หัวใจสำคัญของ Trigger คือการเลือกว่าจะให้มันทำงานตอนไหน โดยมีสองช่วงเวลาหลักคือ BEFORE (ก่อนเกิดเหตุการณ์) และ AFTER (หลังเกิดเหตุการณ์) ซึ่งแต่ละแบบมีจุดประสงค์การใช้งานที่แตกต่างกันอย่างชัดเจนตามสถานการณ์ที่เราต้องการ

ถ้าเราเลือกใช้ BEFORE ระบบจะทำงานก่อนที่ข้อมูลจะถูกเขียนลงในฐานข้อมูลจริง เหมาะสำหรับกรณีที่เราต้องการตรวจสอบข้อมูลก่อน หรือต้องการแก้ไขค่าบางอย่างก่อนบันทึก เช่น การแปลงข้อความให้เป็นตัวพิมพ์ใหญ่ทั้งหมด หรือการตรวจสอบว่าวันที่ที่กรอกเข้ามาถูกต้องตามเงื่อนไขหรือไม่

ในทางกลับกัน AFTER จะทำงานหลังจากที่ข้อมูลถูกบันทึกลงฐานข้อมูลเรียบร้อยแล้ว เหมาะสำหรับงานที่ต้องทำหลังจากเหตุการณ์เสร็จสิ้น เช่น การบันทึกประวัติการแก้ไขข้อมูล (Log) ลงในตารางอื่น หรือการอัปเดตยอดรวมในตารางสรุปผล ซึ่งเป็นขั้นตอนที่ไม่ส่งผลกระทบต่อการบันทึกข้อมูลหลักโดยตรง

ขั้นตอนการเขียน Trigger ชุดแรก

การสร้าง Trigger จะต้องใช้คำสั่ง CREATE TRIGGER ตามด้วยชื่อที่เราตั้งเอง และระบุช่วงเวลาพร้อมเหตุการณ์ที่ต้องการเฝ้าดู เช่น การ INSERT (การเพิ่มข้อมูลใหม่) เข้าไปในตารางที่เรากำหนดไว้ เพื่อให้ระบบเริ่มทำงานตามคำสั่งที่อยู่ภายในบล็อก BEGIN ... END

สมมติว่าเรามีตาราง products และเราอยากให้มีตาราง price_logs คอยเก็บราคาที่ถูกตั้งไว้ทุกครั้งที่มีสินค้าใหม่เข้ามา เราสามารถเขียนคำสั่งเพื่อให้มันบันทึกราคาลงไปในตารางประวัติได้ทันทีโดยไม่ต้องเขียนโค้ดเพิ่มที่ฝั่งแอปพลิเคชัน

สิ่งที่ต้องระวังคืออย่าลืมใช้ DELIMITER (ตัวกำหนดจุดจบคำสั่ง) เพราะปกติฐานข้อมูลจะมองเครื่องหมาย ; เป็นการจบคำสั่งทันที การใช้ DELIMITER // จะช่วยให้เราเขียนโค้ดหลายบรรทัดภายใน Trigger ได้โดยไม่โดนตัดจบก่อนเวลาอันควร

DELIMITER //
CREATE TRIGGER after_product_insert
AFTER INSERT ON products
FOR EACH ROW
BEGIN
    -- บันทึกราคาสินค้าใหม่ลงในตารางประวัติ
    INSERT INTO price_logs (product_id, price)
    VALUES (NEW.id, NEW.price);
END;
//
DELIMITER ;

อธิบายโค้ด:

  • DELIMITER //: บอกฐานข้อมูลว่าให้รอจนกว่าจะเจอ // ถึงจะถือว่าจบคำสั่ง
  • CREATE TRIGGER after_product_insert: สร้างตัวกระตุ้นชื่อนี้ขึ้นมา
  • AFTER INSERT ON products: ให้ทำงานหลังจากที่มีการเพิ่มข้อมูลในตาราง products
  • NEW.id และ NEW.price: คือค่าของข้อมูลใหม่ที่เพิ่งถูกเพิ่มเข้าไป

ผลลัพธ์: เมื่อคุณรันคำสั่ง INSERT INTO products (name, price) VALUES ('Laptop', 20000); ข้อมูลราคาสินค้าจะถูกเพิ่มเข้าไปในตาราง price_logs โดยอัตโนมัติ

การจัดการกับเหตุการณ์ UPDATE และ DELETE

นอกจาก INSERT แล้ว เรายังสามารถเฝ้าดูการ UPDATE (การแก้ไขข้อมูลเดิม) หรือ DELETE (การลบข้อมูลทิ้ง) ได้ด้วย ซึ่งมีประโยชน์มากในการทำระบบติดตามการเปลี่ยนแปลงข้อมูล หรือป้องกันการลบข้อมูลสำคัญทิ้งโดยไม่ตั้งใจ

ในการทำงานกับ UPDATE เราจะมีคำสำคัญคือ NEW และ OLD โดย NEW คือข้อมูลใหม่ที่กำลังจะเปลี่ยนไป ส่วน OLD คือข้อมูลเก่าที่อยู่ในฐานข้อมูลก่อนหน้านี้ การเปรียบเทียบค่าสองตัวนี้ช่วยให้เราเขียนเงื่อนไขที่ซับซ้อนได้ เช่น "ถ้ามีการเปลี่ยนราคาเกิน 50% ให้แจ้งเตือน"

สำหรับการ DELETE เราจะใช้ได้แค่ OLD เท่านั้น เพราะข้อมูลกำลังจะหายไปจากระบบ การใช้ Trigger เก็บข้อมูลที่ถูกลบไปไว้ในตารางสำรอง (Archive) จึงเป็นเทคนิคที่ดีมากในการทำระบบสำรองข้อมูลที่โปรแกรมเมอร์สายองค์กรต้องรู้

CREATE TRIGGER before_product_delete
BEFORE DELETE ON products
FOR EACH ROW
BEGIN
    -- เก็บข้อมูลที่ถูกลบลงตารางสำรองก่อนจะหายไป
    INSERT INTO deleted_products (id, name, deleted_at)
    VALUES (OLD.id, OLD.name, NOW());
END;

อธิบายโค้ด:

  • BEFORE DELETE: ทำงานก่อนที่ข้อมูลจริงจะถูกลบออกจากตาราง products
  • OLD.id และ OLD.name: คือข้อมูลที่อยู่ในแถวนั้นก่อนที่จะถูกลบ
  • NOW(): ฟังก์ชันดึงเวลาปัจจุบันของระบบมาบันทึกไว้

ผลลัพธ์: เมื่อคุณสั่ง DELETE FROM products WHERE id = 1; ข้อมูลของสินค้าชิ้นนั้นจะถูกย้ายไปเก็บไว้ในตาราง deleted_products ก่อนที่ข้อมูลจะถูกลบจริง

สิ่งที่มือใหม่มักพลาดและวิธีแก้ไข

จุดที่มือใหม่มักพลาดบ่อยที่สุดคือการสร้าง Trigger ที่วนลูปไม่รู้จบ เช่น การสั่ง UPDATE ตารางเดิมที่ตัวเองเฝ้าดูอยู่ ทำให้เกิดเหตุการณ์ที่ Trigger ทำงานซ้ำไปมาจนฐานข้อมูลค้าง หรือทำงานผิดพลาดจนต้องรีเซ็ตระบบใหม่ทั้งหมด

อีกเรื่องคือการเผลอไปใส่ Trigger มากเกินความจำเป็นจนทำให้ฐานข้อมูลช้าลง เพราะทุกครั้งที่มีการเขียนข้อมูล ระบบต้องเสียเวลาไปรันคำสั่งที่ฝั่ง Trigger ด้วยเสมอ ถ้าตารางมีการใช้งานหนักมาก การใช้ Trigger จะกลายเป็นคอขวด (จุดที่ทำให้ระบบช้าลง) ของแอปพลิเคชันได้

คำแนะนำคือให้ใช้ Trigger เฉพาะงานที่เกี่ยวข้องกับความถูกต้องของข้อมูลจริงๆ เท่านั้น ถ้างานไหนสามารถเขียนที่ฝั่งโค้ดโปรแกรม (เช่น ภาษา PHP, Python, Node.js) ได้ และทำได้สะดวกกว่า ก็ควรเลือกเขียนที่ฝั่งนั้นแทนเพื่อการดูแลรักษาที่ง่ายในระยะยาว

สรุปการนำไปใช้จริงในโปรเจกต์

การใช้ MySQL หรือ MariaDB Trigger คือการฝากงานไว้กับฐานข้อมูลโดยตรง เพื่อให้มั่นใจว่าไม่ว่าใครจะสั่งงานผ่านช่องทางไหน ข้อมูลก็จะถูกจัดการอย่างถูกต้องเสมอ เช่น การสร้างระบบบัญชีที่ต้องมีการบันทึกยอดคงเหลือทุกครั้งที่มีรายการเดินบัญชี

ตัวอย่างการใช้งานจริงที่แนะนำคือ การทำระบบ Audit Log (บันทึกร่องรอยการแก้ไข) โดยในตารางทุกตารางที่สำคัญ ควรมี Trigger คอยบันทึกว่าใครมาแก้ไขข้อมูลเมื่อไหร่ หรือมีการเปลี่ยนค่าจากอะไรเป็นอะไร ซึ่งเป็นหัวใจสำคัญของระบบที่มีความปลอดภัยสูง

เมื่อคุณเริ่มทำโปรเจกต์แรก ลองนำ Trigger ไปปรับใช้กับการเก็บวันที่แก้ไขข้อมูลล่าสุด (Updated At) โดยอัตโนมัติแทนการเขียนโค้ดสั่งอัปเดตวันที่ในทุกๆ หน้าจอ จะช่วยให้โค้ดของคุณสะอาดขึ้นและลดความซ้ำซ้อนได้อย่างน่าทึ่งครับ

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

MySQL/MariaDB

สอนวิธี Backup และ Restore ฐานข้อมูล MySQL/MariaDB ด้วย mysqldump บน Windows

มือใหม่หัดเขียนโปรแกรมต้องรู้! วิธีสำรองข้อมูล (Backup) และกู้คืน (Restore) ฐานข้อมูลด้วย mysqldump ผ่าน Command Line ป้องกันงานหาย ทำตามได้จริง

1 month ago 9 นาที
22 views
จัดการ User และสิทธิ์ใน MySQL/MariaDB ให้ปลอดภัยด้วยคำสั่ง GRANT และ REVOKE
MySQL/MariaDB

จัดการ User และสิทธิ์ใน MySQL/MariaDB ให้ปลอดภัยด้วยคำสั่ง GRANT และ REVOKE

มือใหม่หัดใช้ฐานข้อมูลต้องรู้! วิธีสร้าง User, กำหนดสิทธิ์ (Permission) และตั้งค่าความปลอดภัยให้ MySQL/MariaDB เพื่อป้องกันข้อมูลรั่วไหลแบบมือโปร

1 month ago 8 นาที
23 views
จัดการฐานข้อมูลให้เป็นมืออาชีพด้วย VIEW และ STORED PROCEDURE ใน MySQL/MariaDB
MySQL/MariaDB

จัดการฐานข้อมูลให้เป็นมืออาชีพด้วย VIEW และ STORED PROCEDURE ใน MySQL/MariaDB

เบื่อไหมกับ Query ยาวๆ ที่เขียนซ้ำไปมา? มาเรียนรู้วิธีใช้ VIEW เพื่อสร้างตารางเสมือน และ STORED PROCEDURE เพื่อเก็บชุดคำสั่งไว้ใช้งาน ช่วยให้โค้ดสะอาดและจัดการง่ายขึ้น

1 month ago 9 นาที
24 views