pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
本章介绍如何编写触发器函数。触发器函数可以用 C 或某些可用的 过程语言编写。目前还无法用 SQL 语言编写触发器函数。
触发器可以定义为在 INSERT、 UPDATE 或 DELETE 操作之前 或之后执行,执行方式既可以是每个被修改的行一次,也可以是每条 SQL 语句一次。一旦触发器事件发生,触发器的 函数就会在恰当的时机被调用以处理该事件。
必须先定义触发器函数,之后才能创建触发器本身。触发器函数必须 声明为不接受参数并返回类型 trigger 的函数。 (触发器函数通过特殊传入的 TriggerData 结构体接收输入,而不是以普通函数参数的形式。)
创建出合适的触发器函数后,就可以使用 CREATE TRIGGER 建立触发器。同一个触发器函数可以供多个触发器使用。
触发器函数向调用它的执行器返回一个表行(即类型 HeapTuple 的值)。在操作之前触发的 触发器可以作出如下选择:
它可以返回一个 NULL 指针,以跳过对当前行的操作 (这样该行就不会被插入/更新/删除)。
仅对于 INSERT 和 UPDATE 触发器,返回的行会成为将要插入的行,或替换正在更新的行。 这使得触发器函数可以修改即将插入或更新的行。
不打算引发上述任何一种行为的 BEFORE 触发器,必须注意把传入的 行原样作为结果返回(也就是说,对于 INSERT 和 UPDATE 触发器返回 NEW 行,对于 DELETE 触发器返回 OLD 行)。
对于在操作之后触发的触发器,其返回值会被忽略,因此它们可以 返回 NULL。
如果为同一关系上的同一事件定义了多个触发器,它们会按触发器 名称的字母顺序触发。对于 BEFORE 触发器,每个触发器返回的、 可能已经被修改过的行都会成为下一个触发器的输入。如果任何 BEFORE 触发器返回一个 NULL 指针,则会放弃该操作, 并且后续触发器不会再触发。
如果触发器函数执行 SQL 命令,那么这些命令可能会再次触发触发器。 这就是所谓的级联触发器。对级联层数没有直接限制。级联还有可能 导致同一个触发器被递归调用;例如,一个 INSERT 触发器可能执行一条向同一个表再插入一行的命令,从而导致该 INSERT 触发器再次触发。因此,在这种场景下, 避免无限递归是触发器编写者自己的责任。
在定义触发器时,可以为它指定参数。 在触发器定义中包含参数,是为了让需求 相似的不同触发器能够调用同一个函数。举例来说,可以有一个 通用触发器函数,它接受两个列名作为参数,把当前用户写入其中 一个列,把当前时间戳写入另一个列。只要编写得当,这个触发器 函数就应独立于它所作用的具体表。因此,同一个函数可用于任何 具有适当列的表上的 INSERT 事件,例如自动 跟踪某个事务表中记录的创建。如果把它定义成 UPDATE 触发器,还可以用来跟踪最近更新 事件。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。