↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4
历史版本。 PostgreSQL 9.4 已结束支持。 2020-02-13. 请参阅 当前版本手册.

41.6. PL/Tcl 中的触发器函数 #

可以用 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

一个 Tcl 列表,包含 CREATE TRIGGER 语句中给出的触发器函数参数。在函数体中,也可以通过 $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 的效果相同,即继续执行操作。其他所有类型的触发器都会忽略返回值。

提示

可使用 Tcl 的array get命令,根据修改后元组的数组表示构造结果列表。

下面是一个简单的触发器函数示例,强制用表中的一个整数值记录该行的更新次数。新插入的行将此值初始化为 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');

注意,触发器函数本身不知道列名,列名通过触发器参数提供。这样,同一个触发器函数就可以在不同表上复用。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.