Chapter 16

Trigger

အခု အခန်းမှာတော့ MySQL ရဲ့ Trigger ကို လေ့လာရမှာပါ။ Trigger ဆိုတာက table တစ်ခု မှာ INSERT , UPDATE , DELETE တစ်ခုခု ဖြစ်လိုက်တိုင်း အလိုလို run သွားမည့် SQL statement တွေ ဖြစ်ပါတယ်။ ကိုယ်တိုင် CALL ခေါ်ပေးစရာ မလိုဘဲ event တစ်ခု ဖြစ်တာ နဲ့ database က အလိုအလျောက် အလုပ်လုပ်ပေးတာပါ။ ဥပမာ data တစ်ခု ပြောင်းလိုက်တိုင်း မှတ်တမ်း (log) ထည့်ချင်တာ၊ ဒါမှမဟုတ် value တွေ ကို အလိုအလျောက် ပြင်ချင်သည့် အခါ မျိုးမှာ Trigger က အသုံးဝင်ပါတယ်။

ဒီ အခန်းမှာ ရှေ့ အခန်းတွေက students table ကို ဆက်လက် အသုံးပြုသွားပါမယ်။

Trigger ရဲ့ အချိန်နှင့် Event

Trigger ကို ဖန်တီးသည့် အခါ အချိန် (timing) နဲ့ event ၂ ခုကို သတ်မှတ်ပေးရပါတယ်။

ဒါကြောင့် BEFORE INSERT , AFTER INSERT , BEFORE UPDATE , AFTER UPDATE , BEFORE DELETE , AFTER DELETE ဆိုပြီး အမျိုးအစား ၆ မျိုး ရှိပါတယ်။

NEW နှင့် OLD

Trigger ထဲမှာ ပြောင်းလဲမည့် data ကို ကိုင်တွယ်ဖို့ အတွက် NEW နဲ့ OLD ဆိုသည့် keyword ၂ ခု ရှိပါတယ်။

Event NEW OLD
INSERT
UPDATE
DELETE

BEFORE INSERT Trigger

အရင်ဆုံး BEFORE INSERT trigger တစ်ခု ဖန်တီးကြည့်ရအောင်။ ကျောင်းသား အသစ် ထည့်သည့် အခါ name ထဲမှာ space အပို တွေ ပါလာရင် ဖြုတ်ပေးမည့် trigger တစ်ခု ဖြစ်ပါတယ်။ BEFORE ဖြစ်သည့် အတွက် data table ထဲ မဝင်ခင် ပြင်ပေးနိုင်ပါတယ်။

DELIMITER //

CREATE TRIGGER trim_student_name
BEFORE INSERT ON students
FOR EACH ROW
BEGIN
    SET NEW.name = TRIM(NEW.name);
END //

DELIMITER ;

အပေါ်မှာ FOR EACH ROW ဆိုတာက ထည့်လိုက်သည့် row တိုင်း အတွက် run မယ် လို့ ပြောတာပါ။ SET NEW.name = TRIM(NEW.name); က table ထဲ မဝင်ခင် name ရဲ့ space အပို တွေ ဖြုတ်ပေးတာ ဖြစ်ပါတယ်။ TRIM ကတော့ စာသား ရဲ့ အရှေ့ အနောက် က space တွေ ကို ဖြုတ်ပေးသည့် function ပါ။

အခု space အပို ပါသည့် name တစ်ခု ထည့်ကြည့်ရအောင်။

INSERT INTO students (name) VALUES ('   Hla Hla   ');

ပြန်ထုတ်ကြည့်ရအောင်။

SELECT student_id, name FROM students WHERE name = 'Hla Hla';
+------------+---------+
| student_id | name    |
+------------+---------+
|         10 | Hla Hla |
+------------+---------+

ထည့်လိုက်သည့် အခါ space အပို တွေ ပါသွားပေမယ့် trigger က table ထဲ မဝင်ခင် ဖြုတ်ပေးလိုက်သည့် အတွက် Hla Hla အဖြစ် သပ်သပ်ရပ်ရပ် ဝင်သွားတာ တွေ့ရပါမယ်။

AFTER INSERT Trigger နှင့် Log Table

အခု data ပြောင်းလဲမှု တွေ ကို မှတ်တမ်း တင်မည့် log table တစ်ခု ဖန်တီးပြီး AFTER INSERT trigger ကို လေ့လာ ကြည့်ရအောင်။ ပထမဆုံး log table ဆောက်ပါမယ်။

CREATE TABLE student_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    student_id INT,
    action VARCHAR(50),
    created_at TIMESTAMP DEFAULT NOW()
);

အခု ကျောင်းသား အသစ် ထည့်တိုင်း student_logs ထဲ မှတ်တမ်း တင်မည့် trigger ကို ဖန်တီးပါမယ်။

DELIMITER //

CREATE TRIGGER log_new_student
AFTER INSERT ON students
FOR EACH ROW
BEGIN
    INSERT INTO student_logs (student_id, action)
    VALUES (NEW.student_id, 'INSERT');
END //

DELIMITER ;

AFTER INSERT ဖြစ်သည့် အတွက် students table ထဲ data ဝင်ပြီးမှ trigger က run ပါတယ်။ ဒါကြောင့် NEW.student_id မှာ database က ပေးလိုက်သည့် student_id ကို ရပါတယ်။

အခု ကျောင်းသား အသစ် ထည့်ကြည့်ရအောင်။

INSERT INTO students (name, dep_code) VALUES ('Su Su', 'CS_101');

student_logs ကို ထုတ်ကြည့်ရအောင်။

SELECT * FROM student_logs;
+----+------------+--------+---------------------+
| id | student_id | action | created_at          |
+----+------------+--------+---------------------+
|  1 |         11 | INSERT | 2020-10-14 01:10:22 |
+----+------------+--------+---------------------+

ကျောင်းသား ထည့်လိုက်တာ နဲ့ trigger က အလိုအလျောက် log ထဲ တစ်ကြောင်း ထည့်ပေးလိုက်တာ တွေ့ရပါမယ်။ ကိုယ်တိုင် log ထည့်ပေးစရာ မလိုတော့ပါဘူး။

AFTER UPDATE Trigger

UPDATE ဖြစ်တဲ့ အခါမှာ OLD နဲ့ NEW ၂ ခုလုံး ကို သုံးနိုင်ပါတယ်။ ကျောင်းသား ရဲ့ dep_code ပြောင်းသွားတိုင်း log ထည့်မည့် trigger ကို ဖန်တီးကြည့်ရအောင်။

DELIMITER //

CREATE TRIGGER log_update_student
AFTER UPDATE ON students
FOR EACH ROW
BEGIN
    IF OLD.dep_code <> NEW.dep_code THEN
        INSERT INTO student_logs (student_id, action)
        VALUES (NEW.student_id, 'UPDATE DEPT');
    END IF;
END //

DELIMITER ;

အပေါ်မှာ OLD.dep_code <> NEW.dep_code ဆိုပြီး department တကယ် ပြောင်းသွား မှ log ထည့်အောင် condition စစ်ထားပါတယ်။ <> ကတော့ "မညီဘူး" (not equal) လို့ အဓိပ္ပါယ် ရပါတယ်။

အခု ကျောင်းသား တစ်ယောက် ရဲ့ department ကို ပြောင်းကြည့်ရအောင်။

UPDATE students SET dep_code = 'CS_102' WHERE student_id = 11;
SELECT * FROM student_logs;
+----+------------+-------------+---------------------+
| id | student_id | action      | created_at          |
+----+------------+-------------+---------------------+
|  1 |         11 | INSERT      | 2020-10-14 01:10:22 |
|  2 |         11 | UPDATE DEPT | 2020-10-14 01:15:48 |
+----+------------+-------------+---------------------+

Department ပြောင်းသွားသည့် အတွက် log ထဲ UPDATE DEPT ဆိုပြီး တစ်ကြောင်း ထပ်တိုးလာတာ တွေ့ရပါမယ်။

BEFORE DELETE Trigger

DELETE ဖြစ်တဲ့ အခါမှာတော့ ဖျက်လိုက်မည့် မူရင်း data ကို OLD နဲ့ ရယူနိုင်ပါတယ်။ ကျောင်းသား ဖျက်လိုက်တိုင်း log ထည့်မည့် trigger ကို ဖန်တီးကြည့်ရအောင်။

DELIMITER //

CREATE TRIGGER log_delete_student
BEFORE DELETE ON students
FOR EACH ROW
BEGIN
    INSERT INTO student_logs (student_id, action)
    VALUES (OLD.student_id, 'DELETE');
END //

DELIMITER ;

DELETE မှာ NEW မရှိသည့် အတွက် OLD.student_id ကို သုံးရတာ ဖြစ်ပါတယ်။

DELETE FROM students WHERE student_id = 11;
SELECT * FROM student_logs;
+----+------------+-------------+---------------------+
| id | student_id | action      | created_at          |
+----+------------+-------------+---------------------+
|  1 |         11 | INSERT      | 2020-10-14 01:10:22 |
|  2 |         11 | UPDATE DEPT | 2020-10-14 01:15:48 |
|  3 |         11 | DELETE      | 2020-10-14 01:20:05 |
+----+------------+-------------+---------------------+

ကျောင်းသား ကို ဖျက်လိုက်သည့် အတွက် log ထဲ DELETE ဆိုပြီး မှတ်တမ်း ဝင်သွားတာ တွေ့ရပါမယ်။ ဒါကြောင့် ကျောင်းသား data ပြောင်းလဲ သမျှ ကို student_logs table မှာ အကုန် ပြန်ကြည့်နိုင်ပါပြီ။

Trigger များကို ကြည့်ခြင်း

Database ထဲမှာ ရှိသည့် trigger တွေ ကို ကြည့်ချင်ရင် အောက်က command ကို သုံးနိုင်ပါတယ်။

SHOW TRIGGERS;

Trigger ဖျက်ခြင်း

ရှိပြီးသား trigger ကို ဖျက်ချင်သည့် အခါ DROP TRIGGER ကို သုံးပါတယ်။

DROP TRIGGER IF EXISTS log_delete_student;

IF EXISTS ကို ထည့်ထားရင် အဲဒီ trigger မရှိ ခဲ့ရင်တောင် error မတက်ဘဲ ကျော်သွားပါမယ်။

အခု ဆိုရင် Trigger ဆိုတာ ဘာလဲ၊ BEFORE နဲ့ AFTER ဘယ်လို ကွာလဲ၊ NEW နဲ့ OLD ကို ဘယ်လို သုံးရလဲ ဆိုတာ သိသွားပါပြီ။ Trigger ကို သုံးခြင်း အားဖြင့် data ပြောင်းလဲမှု တွေ ကို အလိုအလျောက် ထိန်းချုပ် နိုင်ပြီး မှတ်တမ်း တင်ခြင်း တွေ ကိုလည်း လွယ်ကူ စွာ လုပ်ဆောင် နိုင်ပါတယ်။ ဒါပေမယ့် Trigger တွေ များလာရင် ခြေရာခံ ရ ခက်ခဲ နိုင်သည့် အတွက် လိုအပ်သည့် နေရာမှာ သာ သုံးသင့်ပါတယ်။