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 ၂ ခုကို သတ်မှတ်ပေးရပါတယ်။
- အချိန် (Timing) —
BEFOREသို့မဟုတ်AFTER။ Event မဖြစ်ခင် run မလား၊ ဖြစ်ပြီးမှ run မလား ဆိုတာ ဖြစ်ပါတယ်။ - Event —
INSERT,UPDATE,DELETE။ ဘယ် action ဖြစ်တဲ့ အခါ run မလဲ ဆိုတာ ဖြစ်ပါတယ်။
ဒါကြောင့် BEFORE INSERT , AFTER INSERT , BEFORE UPDATE , AFTER UPDATE , BEFORE DELETE , AFTER DELETE ဆိုပြီး အမျိုးအစား ၆ မျိုး ရှိပါတယ်။
NEW နှင့် OLD
Trigger ထဲမှာ ပြောင်းလဲမည့် data ကို ကိုင်တွယ်ဖို့ အတွက် NEW နဲ့ OLD ဆိုသည့် keyword ၂ ခု ရှိပါတယ်။
NEW— အသစ် ဝင်လာမည့် ဒါမှမဟုတ် ပြင်ပြီးသား value (INSERT နဲ့ UPDATE မှာ သုံးနိုင်)OLD— ပြောင်းမသွားခင် ဒါမှမဟုတ် ဖျက်လိုက်မည့် မူရင်း value (UPDATE နဲ့ DELETE မှာ သုံးနိုင်)
| 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 တွေ များလာရင် ခြေရာခံ ရ ခက်ခဲ နိုင်သည့် အတွက် လိုအပ်သည့် နေရာမှာ သာ သုံးသင့်ပါတယ်။