Trigger
Trigger нь хүснэгтэд өөрчлөлт орох үед автоматаар ажиллах тусгай procedure. Хэрэглэгч буюу аппликейшн дуудах шаардлагагүй — MySQL өөрөө ажиллуулна.
Trigger-ийн бүтэц
CREATE TRIGGER trigger_name
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON table_name
FOR EACH ROW
BEGIN
-- ажиллах код
END;
6 төрлийн trigger байдаг:
| | INSERT | UPDATE | DELETE | | ---------- | ------------- | ---------------- | -------------- | | BEFORE | Нэмэхийн өмнө | Өөрчлөхийн өмнө | Устгахын өмнө | | AFTER | Нэмсний дараа | Өөрчилсний дараа | Устгасны дараа |
NEW ба OLD утгууд
| Үйлдэл | NEW | OLD | | ------ | ----------------------- | ---------------------- | | INSERT | Шинэ мөрийн утга | Байхгүй (NULL) | | UPDATE | Өөрчлөлтийн дараах утга | Өөрчлөлтийн өмнөх утга | | DELETE | Байхгүй (NULL) | Устгагдсан мөрийн утга |
AFTER INSERT — нэмсний дараа
-- Хэрэглэгч бүртгүүлэхэд профайл автоматаар үүсгэх
DELIMITER //
CREATE TRIGGER after_user_insert
AFTER INSERT ON users
FOR EACH ROW
BEGIN
INSERT INTO profiles (user_id, display_name, created_at)
VALUES (NEW.id, NEW.username, NOW());
END //
DELIMITER ;
-- Одоо users-д нэмэхэд profiles автоматаар нэмэгдэнэ
INSERT INTO users (username, email) VALUES ('Болд', 'bold@example.com');
-- profiles хүснэгтэд тухайн хэрэглэгчийн мөр үүснэ
BEFORE INSERT — нэмэхийн өмнө
BEFORE trigger нь NEW утгыг өөрчлөх боломжтой — өгөгдөл стандартчилах, шалгахад хэрэглэнэ:
DELIMITER //
CREATE TRIGGER before_user_insert
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
-- И-мэйлийг жижиг үсгээр хөрвүүлж хадгалах
SET NEW.email = LOWER(TRIM(NEW.email));
-- Хэрэглэгчийн нэрийн эхний үсгийг том болгох
SET NEW.username = CONCAT(
UPPER(SUBSTRING(NEW.username, 1, 1)),
LOWER(SUBSTRING(NEW.username, 2))
);
END //
DELIMITER ;
AFTER UPDATE — өөрчилсний дараа
-- Бараа нөөц тодорхой хэмжээнд хүрэхэд мэдэгдэл үүсгэх
DELIMITER //
CREATE TRIGGER after_product_update
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
IF NEW.stock < 10 AND OLD.stock >= 10 THEN
INSERT INTO alerts (product_id, message, created_at)
VALUES (NEW.id, CONCAT(NEW.name, ': нөөц багасаж байна — ', NEW.stock, ' үлдсэн'), NOW());
END IF;
END //
DELIMITER ;
OLD.stock >= 10 AND NEW.stock < 10 — шилжилтийн мөчийг барина. Байнга биш, зааглах үед л ажиллана.
BEFORE DELETE — устгахын өмнө
-- Устгалтыг хориглох
DELIMITER //
CREATE TRIGGER before_order_delete
BEFORE DELETE ON orders
FOR EACH ROW
BEGIN
IF OLD.status = 'paid' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Төлбөр хийгдсэн захиалга устгах боломжгүй';
END IF;
END //
DELIMITER ;
DELETE FROM orders WHERE id = 1;
-- ERROR: Төлбөр хийгдсэн захиалга устгах боломжгүй
SIGNAL SQLSTATE '45000' нь өөрчлөлтийг зогсоож алдааны мэдэгдэл буцаана.
Audit log — өөрчлөлтийн бүртгэл
Ямар өгөгдөл, хэзээ, хэн өөрчилснийг хадгалах нь аюулгүй байдалд чухал:
-- Audit log хүснэгт
CREATE TABLE salary_audit (
id INT PRIMARY KEY AUTO_INCREMENT,
employee_id INT,
old_salary DECIMAL(10,2),
new_salary DECIMAL(10,2),
changed_at DATETIME DEFAULT NOW(),
changed_by VARCHAR(100)
);
-- Цалин өөрчлөгдөх бүрт бүртгэх
DELIMITER //
CREATE TRIGGER after_salary_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
IF OLD.salary != NEW.salary THEN
INSERT INTO salary_audit (employee_id, old_salary, new_salary, changed_by)
VALUES (OLD.id, OLD.salary, NEW.salary, USER());
END IF;
END //
DELIMITER ;
-- Цалин өөрчлөх
UPDATE employees SET salary = 2500000 WHERE id = 5;
-- Бүртгэл шалгах
SELECT * FROM salary_audit;
USER() нь MySQL-д одоо холбогдсон хэрэглэгчийн нэрийг буцаана.
Trigger харах ба устгах
-- Database-н бүх trigger жагсаах
SHOW TRIGGERS FROM myshop;
-- Тодорхой хүснэгтийн trigger
SHOW TRIGGERS FROM myshop WHERE `Table` = 'orders';
-- Trigger устгах
DROP TRIGGER IF EXISTS after_user_insert;
Trigger-ийн хязгаарлалт
Trigger ашиглахад дараах зүйлсийг мэдэх хэрэгтэй:
Recursive trigger: Trigger дотроос тухайн хүснэгтийг өөрчилбөл дахин trigger дуудагдаж давталтад орж болно — анхаарах хэрэгтэй.
Transaction: Trigger нь trigger дуудсан transaction-тай нэг бүлэгт ажилладаг. Trigger алдаа гаргавал бүх transaction ROLLBACK болно.
Хурдны нөлөө: Trigger нь нуугдмал байдлаар ажилладаг тул debug хийхэд хэцүү, performance-д нөлөөлдөг. Энгийн логикийг аппликейшн давхаргад байлгах нь дээр.
Хязгаарлалт:
- Trigger дотроос
CALL procedure()дуудаж болдог - Trigger дотроос
COMMIT/ROLLBACKхийх боломжгүй - Нэг хүснэгтэд нэг төрлийн trigger нэг л байж болно (жишээ:
AFTER INSERTганцхан байна)
Дараагийн хичээлд:
Хэрэглэгч ба эрх — MySQL-д хэрэглэгч үүсгэх, тодорхой эрх олгох, аюулгүй байдлыг хангах аргыг үзнэ.