@freeCodeCamp:数据库触发器让 PostgreSQL 在插入、更新或删除行时自动响应。在本教程中,@…
摘要
本教程来自 freeCodeCamp,讲解 PostgreSQL 数据库触发器的工作原理,包括如何创建触发器、BEFORE 与 AFTER 触发器的区别、行级与语句级触发器,以及如何安全地管理触发器。
查看缓存全文
缓存时间: 2026/08/03 11:40
数据库触发器让 PostgreSQL 能在行被插入、更新或删除时自动响应。
在本教程中,@Iyiola_dev_ 将教你触发器如何工作、如何创建它们,以及何时使用 BEFORE 与 AFTER 触发器。
你还将了解行级触发器与语句级触发器的区别、NEW 和 OLD 如何工作,以及如何安全地检查、禁用和移除触发器。
https://freecodecamp.org/news/what-are-database-triggers-practical-intro-with-postgresql-examples/…
什么是数据库触发器?带有 PostgreSQL 示例的实用介绍
来源:https://www.freecodecamp.org/news/what-are-database-triggers-practical-intro-with-postgresql-examples/
如果你曾经需要数据库自动响应变化——比如记录对敏感表的每次更新、在插入前执行业务规则,或在删除后同步派生数据——那么触发器正是你需要的工具。
数据库触发器是一种函数,当表上发生特定事件时,数据库会自动执行它。你不需要手动调用它。相反,你定义条件,数据库会处理其余部分。
在本教程中,你将学习触发器是什么、它们如何工作、何时使用它们,以及何时避免使用它们。你将通过使用 PostgreSQL 的实用示例进行练习,但核心概念适用于大多数关系数据库。
目录
- 前提条件
- 触发器如何工作
- 如何创建第一个触发器
- BEFORE 与 AFTER 触发器
- 如何使用 AFTER 触发器构建审计日志
- 如何使用 BEFORE 触发器进行验证
- 行级触发器与语句级触发器
- NEW 和 OLD 变量参考
- 如何管理触发器
- 何时使用触发器
- 何时避免使用触发器
- 结论
前提条件
要跟着示例操作,你需要:
- SQL 基础知识(SELECT、INSERT、UPDATE、DELETE)
- 一个正在运行的 PostgreSQL 实例(12 或更高版本)
- 一个 SQL 客户端,如
psql、pgAdmin 或 DBeaver
如果你没有安装 PostgreSQL,可以使用 Neon 或 Supabase 等服务提供的免费云托管实例来跟着操作。
触发器如何工作
从高层来看,触发器有三个部分:
- 事件:什么操作会激活触发器(INSERT、UPDATE、DELETE 或 TRUNCATE)
- 时机:触发器相对于事件在何时触发(BEFORE 或 AFTER)
- 函数:触发器触发时运行什么逻辑
一般流程如下:用户或应用程序对表执行操作,数据库检查是否有与该操作关联的触发器,如果找到匹配项,数据库会自动执行触发器函数。
你可以把触发器看作数据库的事件监听器。就像 JavaScript 的 addEventListener 监听点击或按键一样,数据库触发器监听表上的行级变化。
如何创建第一个触发器
在 PostgreSQL 中,创建触发器是一个两步过程。你首先创建一个触发器函数,然后用 CREATE TRIGGER 语句将该函数附加到表上。
让我们构建一个具体示例。假设你有一个 products 表,并且你希望在每次修改行时自动设置 updated_at 时间戳。
第 1 步 – 创建表
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price NUMERIC(10, 2) NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
第 2 步 – 创建触发器函数
PostgreSQL 中的触发器函数是一种返回 TRIGGER 类型的特殊函数。在函数体内,你可以访问两个重要的变量:NEW(操作后的行)和 OLD(操作前的行)。
CREATE OR REPLACE FUNCTION set_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
这个函数每次运行时都会将 updated_at 列设置为当前时间戳。然后它返回 NEW,告诉 PostgreSQL 继续处理修改后的行。
第 3 步 – 将触发器附加到表
CREATE TRIGGER trigger_set_updated_at
BEFORE UPDATE ON products
FOR EACH ROW
EXECUTE FUNCTION set_updated_at();
让我们分解这个语句的每一部分:
BEFORE UPDATE– 触发器在更新应用到表之前触发ON products– 触发器与products表关联FOR EACH ROW– 该函数对更新影响的每一行运行一次EXECUTE FUNCTION set_updated_at()– 要调用的函数
第 4 步 – 测试
INSERT INTO products (name, price) VALUES ('Wireless Keyboard', 49.99);
-- Wait a moment, then update the row
UPDATE products SET price = 44.99 WHERE name = 'Wireless Keyboard';
SELECT name, price, created_at, updated_at FROM products;
你会看到 updated_at 已自动更新为 UPDATE 操作的时间,即使你没有在查询中显式设置它。这就是触发器在起作用。
BEFORE 与 AFTER 触发器
触发器的时机决定了函数相对于实际数据变化在何时执行。
BEFORE 触发器在行被插入、更新或删除之前运行。当你想要修改或验证传入的数据时,它们很有用。由于更改尚未应用,你可以修改 NEW 行,甚至可以通过返回 NULL 完全取消操作。
AFTER 触发器在行更改已提交到表之后运行。它们适用于副作用,如记录日志、发送通知或更新相关表。此时更改已完成,因此你不能修改该行——但你可以读取 OLD 和 NEW 来查看发生了什么变化。
这里有一个经验法则:当你需要更改或拒绝数据时使用 BEFORE 触发器;当你需要对已完成的更改作出反应时使用 AFTER 触发器。
如何使用 AFTER 触发器构建审计日志
触发器最常见的用途之一是审计日志——记录对重要表所做的每次更改。让我们来构建一个。
第 1 步 – 创建审计表
CREATE TABLE product_audit (
audit_id SERIAL PRIMARY KEY,
product_id INT NOT NULL,
action VARCHAR(10) NOT NULL,
old_price NUMERIC(10, 2),
new_price NUMERIC(10, 2),
changed_by TEXT DEFAULT current_user,
changed_at TIMESTAMP DEFAULT NOW()
);
第 2 步 – 创建审计触发器函数
CREATE OR REPLACE FUNCTION log_product_changes()
RETURNS TRIGGER AS $$
BEGIN
IF TG_OP = 'UPDATE' THEN
INSERT INTO product_audit (product_id, action, old_price, new_price)
VALUES (OLD.id, 'UPDATE', OLD.price, NEW.price);
ELSIF TG_OP = 'DELETE' THEN
INSERT INTO product_audit (product_id, action, old_price)
VALUES (OLD.id, 'DELETE', OLD.price);
ELSIF TG_OP = 'INSERT' THEN
INSERT INTO product_audit (product_id, action, new_price)
VALUES (NEW.id, 'INSERT', NEW.price);
END IF;
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;
这里发生了几件重要的事情。TG_OP 变量是 PostgreSQL 在触发器函数内部提供的一个特殊字符串。它告诉你
相似文章
Postgres by Example
一份使用带注释的SQL示例的PostgreSQL实践入门,涵盖从基础到高级主题。
你只需要PostgreSQL
一份详细指南,介绍如何使用PostgreSQL作为单一数据库来处理金融应用的方方面面,包括模式设计、状态机、触发器和性能优化。
@freeCodeCamp:当数据库写入成功但事件发布失败时,分布式系统可能会崩溃。在本教程中,@pliutau 教…
本教程介绍如何在 Go 和 PostgreSQL 中实现 Outbox 模式,以确保分布式系统中可靠的事件发布,包括构建中继服务和处理至少一次投递。
Postgres事务是分布式系统的超能力
本文解释了如何通过与应用程序数据共置的工作流状态使用Postgres事务,来消除分布式工作流中的幂等性和原子性问题,从而实现精确一次执行。
期待 PostgreSQL 19:是时候了
PostgreSQL 19 终于将引入原生的时态表支持,遵循 SQL:2011 标准,取代过去使用排除约束的手动方法。本文解释了当前方法的局限性以及新功能备受期待的优点。