CodeGym /Các khóa học /SQL SELF /Cơ bản về cú pháp trigger: CREATE TRIGGER, WHEN, EXECUTE ...

Cơ bản về cú pháp trigger: CREATE TRIGGER, WHEN, EXECUTE FUNCTION

SQL SELF
Mức độ , Bài học
Có sẵn

Để tạo trigger trong PostgreSQL, bạn cần xác định các thành phần sau:

  • Tên trigger.
  • Loại sự kiện (INSERT, UPDATE, DELETE).
  • Thời điểm thực thi (BEFORE hoặc AFTER).
  • Bảng mà trigger áp dụng.
  • Hàm sẽ được thực thi (bằng PL/pgSQL hoặc ngôn ngữ khác).

Đây là cấu trúc chung của lệnh:

CREATE TRIGGER ten_trigger
[BEFORE | AFTER] {INSERT | UPDATE | DELETE}
ON ten_bang
[FOR EACH ROW | FOR EACH STATEMENT]
WHEN (dieu_kien)
EXECUTE FUNCTION ten_ham();

Ví dụ trigger đơn giản

Cùng tạo một bảng cơ bản students và thêm trigger sẽ chạy sau khi thêm bản ghi mới.

Đầu tiên tạo bảng students

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Có gì ở đây vậy? Tụi mình vừa tạo bảng với các trường id, namelast_modified. Trường last_modified sẽ lưu ngày giờ lần cuối bản ghi được sửa.

Trigger luôn gắn với hàm. Đầu tiên, tạo một hàm đơn giản để cập nhật trường last_modified mỗi khi thêm bản ghi:

CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
    -- Đặt ngày giờ hiện tại vào trường last_modified
    NEW.last_modified := CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Đây là phép thuật gì vậy?

  1. NEW — biến đặc biệt chứa giá trị mới của dòng (cho sự kiện INSERT hoặc UPDATE).
  2. CURRENT_TIMESTAMP — hàm trả về ngày giờ hiện tại.
  3. RETURN NEW — trả về dòng đã chỉnh sửa để lưu lại.

Giờ tạo trigger luôn nhé:

CREATE TRIGGER set_last_modified
AFTER INSERT
ON students
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();

Giải thích:

  • AFTER INSERT: trigger chạy sau khi thêm dòng mới.
  • ON students: trigger áp dụng cho bảng students.
  • FOR EACH ROW: trigger chạy cho từng dòng mới.
  • EXECUTE FUNCTION: chỉ định hàm sẽ được gọi.

Kiểm tra trigger hoạt động

Cùng test trigger nhé:

INSERT INTO students (name) VALUES ('Alice');
SELECT * FROM students;

Bạn sẽ thấy kết quả kiểu như này:

id name last_modified
1 Alice 2023-10-15 14:23:45

Trigger tự động cập nhật trường last_modified. Phép thuật hả? Không đâu, chỉ là PostgreSQL thôi.

Dùng điều kiện với WHEN

Đôi khi bạn không muốn trigger chạy mọi lúc, mà chỉ khi có điều kiện nhất định. Đó là lúc dùng từ khóa WHEN.

Cùng xem ví dụ trigger chỉ chạy với giá trị nhất định nhé.

Giả sử bạn muốn trigger chỉ chạy cho sinh viên tên "Alice". Sửa trigger lại như sau:

CREATE OR REPLACE FUNCTION update_last_modified_condition()
RETURNS TRIGGER AS $$
BEGIN
    NEW.last_modified := CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER set_last_modified_condition
AFTER INSERT
ON students
FOR EACH ROW
WHEN (NEW.name = 'Alice')
EXECUTE FUNCTION update_last_modified_condition();

Giờ trigger sẽ cập nhật trường last_modified chỉ cho sinh viên tên "Alice".

Test thử nhé:

INSERT INTO students (name) VALUES ('Alice');
INSERT INTO students (name) VALUES ('Bob');
SELECT * FROM students;

Kết quả:

id name last_modified
1 Alice 2023-10-15 14:30:00
2 Bob (NULL)

Lưu ý: với sinh viên "Bob", trường last_modified vẫn trống vì trigger không chạy.

Liên kết trigger với hàm: EXECUTE FUNCTION

Hàm là trái tim của mọi trigger. Trigger không thể tồn tại nếu không có hàm xác định logic của nó. Trong PostgreSQL, bạn có thể viết hàm bằng PL/pgSQL hoặc các ngôn ngữ khác như Python hay C.

Cùng xem ví dụ dùng hàm PL/pgSQL nhé.

Tạo hàm ghi log thay đổi vào bảng riêng audit_log.

Đầu tiên tạo bảng audit_log

CREATE TABLE audit_log (
    id SERIAL PRIMARY KEY,
    operation TEXT NOT NULL,
    student_id INTEGER NOT NULL,
    log_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Giờ là hàm:

CREATE OR REPLACE FUNCTION log_insert()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO audit_log (operation, student_id)
    VALUES ('INSERT', NEW.id);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Viết trigger luôn:

CREATE TRIGGER log_student_insert
AFTER INSERT
ON students
FOR EACH ROW
EXECUTE FUNCTION log_insert();

Và test thử:

INSERT INTO students (name) VALUES ('Charlie');
SELECT * FROM audit_log;

Bạn sẽ thấy kết quả kiểu như này:

id operation student_id log_time
1 INSERT 3 2023-10-15 14:35:00

Trigger tự động ghi log cho bản ghi mới.

Lỗi và lưu ý khi làm việc với trigger

Lỗi: thiếu hàm. Nếu bạn cố tạo trigger mà không có hàm, PostgreSQL sẽ báo lỗi. Luôn tạo hàm trước khi tạo trigger nhé.

Vấn đề hiệu năng. Có quá nhiều trigger hoặc hàm phức tạp có thể làm database chậm đi. Dùng trigger cẩn thận nha.

Đệ quy. Nếu trigger thay đổi chính bảng mà nó đang chạy, có thể gây vòng lặp vô hạn. Dùng điều kiện WHEN để tránh chuyện này.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION