↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本。 PostgreSQL 7.0 已结束支持。 请参阅 当前版本手册.

第 47 章 触发器

Postgres 有多种服务器端函数接口。服务器端函数可以用 SQL、PLPGSQL、TCL 或 C 编写。除 SQL 外,触发器函数可以用这些语言中的任何一种编写。注意,当前版本不支持语句(STATEMENT)级触发器事件。目前可以把 BEFORE 或 AFTER 指定在一个元组的 INSERT、DELETE 或 UPDATE 上作为触发器事件。

47.1. 触发器创建

一旦触发器事件发生,触发器管理器(由执行器调用)就会初始化全局结构 TriggerData *CurrentTriggerData(下文描述),并调用触发器函数来处理该事件。

必须先创建触发器函数,然后才能创建触发器,它声明为不接受参数并返回 opaque 的函数。

创建触发器的语法如下:

CREATE TRIGGER trigger [ BEFORE | AFTER ] [ INSERT | DELETE | UPDATE [ OR ... ] ]
    ON relation FOR EACH [ ROW | STATEMENT ]
    EXECUTE PROCEDURE procedure
     (args);

其中各个参数为:

trigger

触发器的名称在你将来需要删除该触发器时使用。它被用作 DROP TRIGGER 命令的一个参数。

BEFORE
AFTER

决定函数是在事件之前还是之后被调用。

INSERT
DELETE
UPDATE

命令的下一个元素决定哪些事件会触发该函数。可以用 OR 分隔指定多个事件。

relation

关系名指出该事件作用于哪个表。

ROW
STATEMENT

FOR EACH 子句决定触发器是针对每个受影响的行触发,还是在整条语句完成之前(或之后)触发。目前只支持 ROW 的情形。

procedure

过程名是要被调用的函数。

args

通过 CurrentTriggerData 结构传给函数的参数。向函数传递参数的目的,是为了让需求相似的不同触发器能够调用同一个函数。

另外,procedure 也可以用于触发不同的关系(这类函数被称为 "通用触发器函数")。

作为同时使用上述两个特性的例子,可以有一个通用函数,它接受两个列名作为参数,把当前用户写入其中一个列,把当前时间戳写入另一个列。这样就可以在 INSERT 事件上编写触发器,例如自动跟踪某个事务表中记录的创建。如果用在 UPDATE 事件上,它还可以作为一个"最近更新"函数使用。

触发器函数向调用它的执行器返回 HeapTuple。对于在 INSERT、DELETE 或 UPDATE 操作之后触发的触发器,该返回值会被忽略,但它允许 BEFORE 触发器:

  • 返回 NULL,以跳过对当前元组的操作(这样该元组就不会被插入/更新/删除)。

  • 返回一个指向另一个元组的指针(仅 INSERT 和 UPDATE),该元组将被插入(如果是 UPDATE,则作为被更新元组的新版本),以取代原来的元组。

注意,CREATE TRIGGER 处理器不执行任何初始化。这一点将来会改变。另外,如果为同一关系上的同一事件定义了多个触发器,触发器的触发顺序是不可预测的。这一点将来也可能会改变。

如果触发器函数执行 SQL 查询(使用 SPI),那么这些查询可能会再次触发触发器。这就是所谓的级联触发器。对级联层数没有明确的限制。

如果一个触发器由 INSERT 触发,而又向同一个关系插入了一个新元组,那么该触发器会再次被触发。目前,对于这类情形没有提供任何同步(等)机制,但这一点将来可能改变。目前,回归测试中的函数 funny_dup17() 使用了一些技巧来停止对自身的递归(级联)……

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.