目录

pgsql-13 触发器详解

13 - 触发器详解

1. 📖 概述

触发器是在特定事件(INSERT/UPDATE/DELETE)发生时自动执行的函数。本章介绍PostgreSQL触发器的使用。

2. 🔔 触发器基础

2.1 创建触发器

-- 1. 创建触发器函数
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 2. 创建触发器
CREATE TRIGGER trigger_update_timestamp
BEFORE UPDATE ON users
FOR EACH ROW
EXECUTE FUNCTION update_timestamp();

-- 测试
UPDATE users SET username = 'new_name' WHERE id = 1;
-- updated_at会自动更新

2.2 触发器时机

-- BEFORE: 在操作执行前
CREATE TRIGGER before_insert
BEFORE INSERT ON products
FOR EACH ROW
EXECUTE FUNCTION validate_product();

-- AFTER: 在操作执行后
CREATE TRIGGER after_insert
AFTER INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION send_order_notification();

-- INSTEAD OF: 仅用于视图,替代原操作
CREATE TRIGGER instead_of_update
INSTEAD OF UPDATE ON view_name
FOR EACH ROW
EXECUTE FUNCTION custom_update();

3. 💡 实用示例

3.1 审计日志

CREATE TABLE audit_log (
    id SERIAL PRIMARY KEY,
    table_name TEXT,
    operation TEXT,
    old_data JSONB,
    new_data JSONB,
    user_id INTEGER,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE OR REPLACE FUNCTION audit_trigger()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO audit_log (table_name, operation, old_data, new_data, user_id)
    VALUES (
        TG_TABLE_NAME,
        TG_OP,
        row_to_json(OLD),
        row_to_json(NEW),
        current_setting('app.user_id', TRUE)::INTEGER
    );
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER users_audit
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW
EXECUTE FUNCTION audit_trigger();

3.2 自动计算

-- 订单金额自动计算
CREATE OR REPLACE FUNCTION calculate_order_total()
RETURNS TRIGGER AS $$
BEGIN
    UPDATE orders
    SET total_amount = (
        SELECT SUM(quantity * price)
        FROM order_items
        WHERE order_id = NEW.order_id
    )
    WHERE id = NEW.order_id;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_calculate_total
AFTER INSERT OR UPDATE OR DELETE ON order_items
FOR EACH ROW
EXECUTE FUNCTION calculate_order_total();

4. 📚 下一步

学习事务与并发控制


关键要点:

  • BEFORE触发器可以修改NEW
  • AFTER触发器不能修改数据
  • 避免触发器死循环
  • 审计日志常用触发器实现