Để 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 (
BEFOREhoặcAFTER). - 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, name và last_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?
NEW— biến đặc biệt chứa giá trị mới của dòng (cho sự kiệnINSERThoặcUPDATE).CURRENT_TIMESTAMP— hàm trả về ngày giờ hiện tại.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ảngstudents.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.
GO TO FULL VERSION