Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Tạo Trigger BEFORE INSERT trong MySQL

Vấn đề: Tự động kiểm tra/ràng buộc trước khi chèn dữ liệu

Cần ngăn chặn INSERT nếu tổng cột Value trong bảng đã đạt 60.

Giải pháp: Trigger BEFORE INSERT

Trigger kích hoạt trước mỗi hàng chèn (FOR EACH ROW). Dùng SIGNAL để ném lỗi và hủy chèn.

1. Cú pháp tạo Trigger

DELIMITER //

CREATE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
    -- logic kiểm tra
    IF (condition) THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error message';
    END IF;
END //

DELIMITER ;

2. Ví dụ cụ thể: Tổng Value không vượt quá 60

CREATE TABLE DemoTable (Value INT);

DELIMITER //
CREATE TRIGGER sum_is_60
BEFORE INSERT ON DemoTable
FOR EACH ROW
BEGIN
    DECLARE custom_message VARCHAR(256);
    IF (SELECT SUM(Value) FROM DemoTable) = 60 THEN
        SET custom_message = 'Cannot insert: sum(Value) would exceed 60';
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = custom_message;
    END IF;
END //
DELIMITER ;

3. Kiểm tra Trigger

INSERT INTO DemoTable VALUES (10); -- OK, sum=10
INSERT INTO DemoTable VALUES (20); -- OK, sum=30
INSERT INTO DemoTable VALUES (30); -- OK, sum=60
INSERT INTO DemoTable VALUES (40); -- LỖI: sum sẽ thành 100 > 60

4. Kết quả lỗi

ERROR 1644 (45000): Cannot insert: sum(Value) would exceed 60

Giải thích

  • BEFORE INSERT – Chạy trước khi hàng được ghi vào bảng.
  • FOR EACH ROW – Chạy cho mỗi hàng INSERT (INSERT nhiều hàng → trigger chạy nhiều lần).
  • NEW.Value – Truy cập giá trị mới sắp chèn (ví dụ: IF (SELECT SUM(Value) FROM DemoTable) + NEW.Value > 60 chính xác hơn).
  • SIGNAL SQLSTATE '45000' – Ném ngoại lệ người dùng tự định nghĩa (45000 = unhandled user-defined exception).

Cải tiến logic chính xác hơn

IF (SELECT COALESCE(SUM(Value), 0) FROM DemoTable) + NEW.Value > 60 THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Sum would exceed 60';
END IF;

Dùng COALESCE xử lý bảng rỗng (SUM trả NULL). Cộng NEW.Value để kiểm tra sau khi chèn.

Lưu ý

  • Trigger làm chậm INSERT – chỉ dùng khi cần thiết (ràng buộc phức tạp không thể dùng CHECK constraint).
  • MySQL 8.0.16+ hỗ trợ CHECK constraint – ưu tiên dùng cho ràng buộc đơn giản.
  • Xem trigger: SHOW TRIGGERS; hoặc SELECT * FROM information_schema.triggers;.