假设我们有一张表,专门存学生的数据。在这张表里,我们想每次加新学生的时候,自动更新last_modified(记录最后修改时间)这个字段。这个字段很重要,用来追踪数据变化和管理数据。
流程大概是这样的:
- 每当表里加一条新记录,
last_modified字段会自动变成当前的日期和时间。 - 我们会用
AFTER INSERT触发器,这个触发器会在数据插入成功后执行。
写触发器用的函数
首先要用PL/pgSQL写一个函数。这个函数会负责更新我们表里的last_modified字段。函数是触发器必须要有的,因为触发器只是告诉数据库“要干嘛”,具体怎么干都是函数来实现的。
先来建个表:
-- 创建表 students
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
age INT NOT NULL,
last_modified TIMESTAMP
);
现在写个函数来更新last_modified字段:
-- 更新last_modified的函数
CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
-- 把当前时间写进last_modified字段
NEW.last_modified := NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
来解释一下这个函数到底干了啥:
CREATE OR REPLACE FUNCTION update_last_modified()— 创建一个叫update_last_modified的函数。如果已经有同名的,会替换掉。RETURNS TRIGGER— 说明这个函数是给触发器用的。NEW.last_modified := NOW();— 用NOW()函数把当前时间写进last_modified字段。RETURN NEW;— 返回更新后的记录。AFTER类触发器必须要有这一步。
创建触发器
函数写好后,我们就能建触发器,把它绑到students表上。方法如下:
-- 插入后触发的触发器
CREATE TRIGGER set_last_modified
AFTER INSERT ON students
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();
这里做了这些事:
CREATE TRIGGER set_last_modified— 创建一个叫set_last_modified的触发器。AFTER INSERT— 这个触发器会在插入新行后执行。ON students— 触发器绑在students表上。FOR EACH ROW— 每插入一行都会执行一次。EXECUTE FUNCTION update_last_modified();— 调用我们刚写的函数。
注意:触发器名(set_last_modified)和函数名(update_last_modified)你可以随便起,不过最好按规范来,这样代码更容易懂。
测试触发器
来看看触发器到底好不好使。先往students表里插几条数据:
-- 往表里插数据
INSERT INTO students (name, age) VALUES ('伊万 伊万诺夫', 20);
INSERT INTO students (name, age) VALUES ('安娜 彼得罗娃', 22);
现在查查表里都有什么:
-- 查看表里的数据
SELECT * FROM students;
预期结果大概是这样:
| id | name | age | last_modified |
|---|---|---|---|
| 1 | 奥托 明 | 20 | 2023-10-10 14:30:45 |
| 2 | 安娜 宋 | 22 | 2023-10-10 14:31:12 |
你会发现,last_modified字段已经自动填上了每条记录插入时的时间。
可能遇到的错误
- 错误:"relation does not exist" 创建触发器时报错。这个错一般是因为
students表还没建好。先建表再建触发器。 - 权限错误。如果数据库用户没权限建函数或触发器,触发器就建不起来。检查一下用户权限。
- 触发器里没写函数调用。如果你忘了写
EXECUTE FUNCTION update_last_modified(),触发器啥也不会干。
触发器进阶:加条件
实际开发中,有时候我们只想在满足某些条件时才让触发器执行。比如说,如果age字段小于18,我们就不想更新last_modified。可以用WHEN条件来搞定:
-- 带条件的触发器
CREATE TRIGGER set_last_modified
AFTER INSERT ON students
FOR EACH ROW
WHEN (NEW.age >= 18)
EXECUTE FUNCTION update_last_modified();
这样只有年龄大于等于18的学生,last_modified才会被更新。
实际应用
像这种触发器,在实际项目里用得挺多。举几个例子:
- 自动更新记录最后修改时间(就像我们现在做的)。
- 监控数据库变化,把这些变化写进日志表。
- 保证数据一致性,比如操作前检查相关表的数据。
- 做数据审计,满足法律或公司要求。
这些技能特别有用,尤其是你要做那种对数据准确性和可靠性要求很高的系统,比如银行系统、库存管理系统或者CRM。
GO TO FULL VERSION