触发器过程也可以用 PL/Tcl 编写。PostgreSQL要求能作为触发器被调用的过程必须被声明为一个没有参数并且返回类型为trigger
的函数。
来自于触发器管理器的信息通过下列变量被传递给过程体:
$TG_name
CREATE TRIGGER
语句中触发器的名字。
$TG_relid
导致触发器过程被调用的表的对象 ID。
$TG_table_name
导致触发器过程被调用的表的名字。
$TG_table_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
为空。该数组以列名为索引。为空的列不会出现在数组中。对于语句级触发器这个变量不会被设置。
$OLD
对于UPDATE
或者DELETE
动作是一个包含着新表行值的关联数组,对于INSERT
为空。该数组以列名为索引。为空的列不会出现在数组中。对于语句级触发器这个变量不会被设置。
$args
在CREATE TRIGGER
语句中对过程给出的参数的 Tcl 列表。在过程体中也可以用$1
... $
来访问这些参数。
n
触发器过程的返回值可以是OK
或者SKIP
,
还可以是一个列名/值对的列表。如果返回值是OK
,引发触发器的操作
(INSERT
/UPDATE
/DELETE
)将正常继续。
SKIP
告诉触发器管理器禁止对这一行的操作。如果返回的是列表,
它告诉 PL/Tcl 返回一个被修改行给触发器管理器;
修改后的行的内容由列表中的列名和值指定。列表中未提及的任何列都设置为空。
返回修改后的行仅对行级的BEFORE
INSERT
或者
UPDATE
触发器有意义,对这些触发器将插入被修改行而不是插入
$NEW
中给定的行;或者对于行级INSTEAD OF
INSERT
或者UPDATE
触发器也有意义,在其中返回的行被用作
INSERT RETURNING
以及UPDATE RETURNING
子句的源数据。
在行级BEFORE
DELETE
或INSTEAD
OF
DELETE
触发器中,返回修改后的行和返回OK
有相同的影响,
即操作继续。所有其他类型的触发器都忽略触发器返回值。
结果列表可以使用array get
Tcl命令从修改过的元组的数组表示中获得。
这里有一个触发器过程的例子,它用一个表中的整数值来跟踪在行上被执行的更新数。对于被插入的新行,该值被初始化为 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 PROCEDURE trigfunc_modcount('modcnt');
注意触发器过程本身不知道列名,列名由触发器参数提供。这让触发器过程可以被重用于不同的表。