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