触发器函数可以用 PL/Tcl 编写。 PostgreSQL 要求要被用作触发器调用的函数必须声明为无参数且返回类型为 trigger
的函数。
来自触发器管理器(trigger manager)的信息通过以下变量传递给函数体:
$TG_name
CREATE TRIGGER
语句中触发器的名称。
$TG_relid
导致触发器函数被调用的表的 OID(对象标识符)。
$TG_table_name
导致触发器函数被调用的表的名称。
$TG_table_schema
导致触发器函数被调用的表的模式(schema)名称。
$TG_relatts
表的列名称的 Tcl 列表,前面有一个空列表元素。因此,使用 Tcl 的 lsearch
命令在列表中查找列名时,返回的元素编号从 1 开始,对于第一个列,与 PostgreSQL 中通常编号方式相同。(已被删除的列的位置也会出现空列表元素,以确保其右侧列的属性编号正确。)
$TG_when
根据触发器事件类型,字符串为 BEFORE
、AFTER
或 INSTEAD OF
。
$TG_level
根据触发器事件类型,字符串为 ROW
或 STATEMENT
。
$TG_op
根据触发器事件类型,字符串为 INSERT
、UPDATE
、DELETE
或 TRUNCATE
。
$NEW
一个关联数组,包含 INSERT
或 UPDATE
操作的新行值,对于 DELETE
操作为空。数组以列名作为索引。值为 NULL 的列不会出现在数组中。此变量对于语句级触发器不设置。
$OLD
一个关联数组,包含 UPDATE
或 DELETE
操作的旧行值,对于 INSERT
操作为空。数组以列名作为索引。值为 NULL 的列不会出现在数组中。此变量对于语句级触发器不设置。
$args
CREATE TRIGGER
语句中给出的函数参数的 Tcl 列表。这些参数在函数体中也可以通过 $1
... $
访问。n
触发器函数的返回值可以是字符串 OK
或 SKIP
,也可以是列名/值对的列表。如果返回值为 OK
,则触发该触发器的操作(INSERT
/UPDATE
/DELETE
)将正常进行。SKIP
会告知触发器管理器静默地阻止对该行的操作。如果返回的是一个列表,它会告诉 PL/Tcl 将一个修改后的行返回给触发器管理器;修改后的行的内容由列表中的列名和值指定。列表中未提及的任何列都将设置为 NULL。返回一个修改后的行仅对行级 BEFORE
INSERT
或 UPDATE
触发器有意义,在这种情况下,返回的修改后的行将替代 $NEW
中的行被插入;或者对于行级 INSTEAD OF
INSERT
或 UPDATE
触发器,返回的行将用作 INSERT RETURNING
或 UPDATE RETURNING
子句的源数据。在行级 BEFORE
DELETE
或 INSTEAD OF
DELETE
触发器中,返回修改后的行与返回 OK
的效果相同,即操作将继续进行。对于所有其他类型的触发器,将忽略触发器返回值。
结果列表可以由 Tcl 命令 array get
从修改后的元组(tuple)的数组表示形式生成。
这是一个小的示例触发器函数,它强制一个表中的整数值来跟踪对该行执行的更新次数。对于新插入的行,该值初始化为 0,然后在每次更新操作时递增。
CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS $$ switch $TG_op { INSERT { set NEW($1) 0 } UPDATE { set NEW($1) $OLD($1) incr NEW($1) } default { return OK } } return [array get NEW] $$ LANGUAGE pltcl; CREATE TABLE mytab (num integer, description text, modcnt integer); CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab FOR EACH ROW EXECUTE FUNCTION trigfunc_modcount('modcnt');
请注意,触发器函数本身不知道列名;列名是从触发器参数中提供的。这使得触发器函数可以与不同的表重用。
如果您在文档中发现任何不正确之处、与您对特定功能的实际体验不符之处或需要进一步澄清之处,请使用此表单来报告文档问题。