@freeCodeCamp:数据库触发器让 PostgreSQL 在插入、更新或删除行时自动响应。在本教程中,@…

X AI KOLs Timeline 工具

摘要

本教程来自 freeCodeCamp,讲解 PostgreSQL 数据库触发器的工作原理,包括如何创建触发器、BEFORE 与 AFTER 触发器的区别、行级与语句级触发器,以及如何安全地管理触发器。

数据库触发器让 PostgreSQL 在插入、更新或删除行时自动响应。 在本教程中,@Iyiola_dev_ 将教你触发器的工作原理、如何创建触发器,以及何时使用 BEFORE 与 AFTER 触发器。 你还将学习行级与语句级触发器、NEW 和 OLD 的工作方式,以及如何安全地检查、禁用和删除触发器。 https://freecodecamp.org/news/what-are-database-triggers-practical-intro-with-postgresql-examples/…
查看原文
查看缓存全文

缓存时间: 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 的实用示例进行练习,但核心概念适用于大多数关系数据库。

目录

前提条件

要跟着示例操作,你需要:

  • SQL 基础知识(SELECT、INSERT、UPDATE、DELETE)
  • 一个正在运行的 PostgreSQL 实例(12 或更高版本)
  • 一个 SQL 客户端,如 psql、pgAdmin 或 DBeaver

如果你没有安装 PostgreSQL,可以使用 NeonSupabase 等服务提供的免费云托管实例来跟着操作。

触发器如何工作

从高层来看,触发器有三个部分:

  1. 事件:什么操作会激活触发器(INSERT、UPDATE、DELETE 或 TRUNCATE)
  2. 时机:触发器相对于事件在何时触发(BEFORE 或 AFTER)
  3. 函数:触发器触发时运行什么逻辑

一般流程如下:用户或应用程序对表执行操作,数据库检查是否有与该操作关联的触发器,如果找到匹配项,数据库会自动执行触发器函数。

你可以把触发器看作数据库的事件监听器。就像 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 触发器在行更改已提交到表之后运行。它们适用于副作用,如记录日志、发送通知或更新相关表。此时更改已完成,因此你不能修改该行——但你可以读取 OLDNEW 来查看发生了什么变化。

这里有一个经验法则:当你需要更改或拒绝数据时使用 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

Hacker News Top

一份使用带注释的SQL示例的PostgreSQL实践入门,涵盖从基础到高级主题。

你只需要PostgreSQL

Lobsters Hottest

一份详细指南,介绍如何使用PostgreSQL作为单一数据库来处理金融应用的方方面面,包括模式设计、状态机、触发器和性能优化。

Postgres事务是分布式系统的超能力

Hacker News Top

本文解释了如何通过与应用程序数据共置的工作流状态使用Postgres事务,来消除分布式工作流中的幂等性和原子性问题,从而实现精确一次执行。

期待 PostgreSQL 19:是时候了

Hacker News Top

PostgreSQL 19 终于将引入原生的时态表支持,遵循 SQL:2011 标准,取代过去使用排除约束的手动方法。本文解释了当前方法的局限性以及新功能备受期待的优点。