pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
Postgres 有多种客户端接口,例如 Perl、Tcl、 Python 和 C,还有两种过程语言(PL)。 也可以把 C 函数作为触发器动作调用。注意,当前版本不支持 语句(STATEMENT)级触发器事件。目前可以把 BEFORE 或 AFTER 指定在 一个元组的 INSERT、DELETE 或 UPDATE 上作为触发器事件。
一旦触发器事件发生,触发器管理器(由执行器调用)就会初始化 全局结构 TriggerData *CurrentTriggerData(下文描述),并调用触发器 函数来处理该事件。
必须先创建触发器函数,然后才能创建触发器,它声明为不接受参数 并返回 opaque 的函数。
创建触发器的语法如下:
CREATE TRIGGER <trigger name> <BEFORE|AFTER> <INSERT|DELETE|UPDATE>
ON <relation name> FOR EACH <ROW|STATEMENT>
EXECUTE PROCEDURE <procedure name> (<function args>);
触发器的名称在你将来需要删除该触发器时使用。它被用作 DROP TRIGGER 命令的一个参数。
下一个词决定函数是在事件之前还是之后被调用。
命令的下一个元素决定该函数将在哪些事件上触发。可以用 OR 分隔指定多个事件。
关系名决定该事件作用于哪个表。
FOR EACH 语句决定触发器是针对每个受影响的行触发,还是在整条 语句完成之前(或之后)触发。
过程名是被调用的 C 函数。
参数通过 CurrentTriggerData 结构传给函数。向函数传递参数的目的, 是为了让需求相似的不同触发器能够调用同一个函数。
另外,函数也可以用于触发不同的关系(这类函数被称为“通用触发器 函数”)。
作为同时使用上述两个特性的例子,可以有一个通用函数,它接受两个 字段名作为参数,把当前用户写入其中一个字段,把当前时间戳写入另一个 字段。这样就可以在 INSERT 事件上编写触发器,例如自动跟踪某个事务表 中记录的创建。如果用在 UPDATE 事件上,它还可以作为一个“最近更新” 函数使用。
触发器函数向调用它的执行器返回 HeapTuple。对于在 INSERT、DELETE 或 UPDATE 操作之后触发的触发器,该返回值会被忽略,但它允许 BEFORE 触发器: - 返回 NULL,以跳过对当前元组的操作(这样该元组就不会被 插入/更新/删除); - 返回一个指向另一个元组的指针(仅 INSERT 和 UPDATE),该元组 将被插入(如果是 UPDATE,则作为被更新元组的新版本),以取代 原来的元组。
注意,CREATE TRIGGER 处理器不执行任何初始化。这一点将来会改变。 另外,如果为同一关系上的同一事件定义了多个触发器,触发的顺序 是不可预测的。这一点将来也可能会改变。
如果触发器函数执行 SQL 查询(使用 SPI),那么这些查询可能会再次 触发触发器。这就是所谓的级联触发器。对级联层数没有明确的限制。
如果一个触发器由 INSERT 触发,而又向同一个关系插入了一个新元组, 那么该触发器会再次被触发。目前,对于这类情形没有提供任何同步 (等)机制,但这一点将来可能改变。目前,回归测试中的函数 funny_dup17() 使用了一些技巧来停止对自身的递归(级联)……
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。