Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

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

触发器函数可以用 PL/Tcl 编写。PostgreSQL 要求要作为触发器调用的函数必须声明为没有参数的函数,并带有 trigger 的返回类型。

触发器管理器中的信息会以下面的变量传递给函数主体

$TG_name

CREATE TRIGGER 语句的触发器名称。

$TG_relid

导致调用触发器函数的表的对象 ID。

$TG_table_name

导致调用触发器函数的表名称。

$TG_table_schema

导致调用触发器函数的表的模式。

$TG_relatts

表列名称的 Tcl 列表,带有前缀空列表元件。因此,用 Tcllsearch 命令在列表中查找列名称会返回元件的编号,第一列从 1 开始,列号的顺序与 PostgreSQL 中列号的顺序相同。(空列表元件也会出现在已删除的列的位置,以便属性编号对它们右边的列是正确的。)

$TG_when

字符串 BEFOREAFTERINSTEAD OF,具体取决于触发器事件的类型。

$TG_level

字符串 ROWSTATEMENT,具体取决于触发器事件的类型。

$TG_op

字符串 INSERTUPDATEDELETETRUNCATE,具体取决于触发器事件的类型。

$NEW

包含 INSERTUPDATE 动作的新表格行的值的关联数组,或对于 DELETE 为空。数组通过列名称索引。为 null 的列不会出现在数组中。语句级别的触发器不会为此设置值。

$OLD

包含 UPDATEDELETE 动作的旧表格行的值的关联数组,或对于 INSERT 为空。数组通过列名称索引。为 null 的列不会出现在数组中。语句级别的触发器不会为此设置值。

$args

CREATE TRIGGER 语句中给出的函数参数的 Tcl 列表。在函数主体中,也可以将这些参数作为 $1 ... $n 访问。

触发器函数的返回值可以是字符串 OKSKIP,或列名/值的列表。如果返回值是 OK,触发触发器的操作(INSERT/UPDATE/DELETE)将正常进行。 SKIP 告诉触发器管理器静默抑制这一行的操作。如果返回列表,则该列表告诉 PL/Tcl 将修改后的行返回给触发器管理器;修改后的行内容由列表中的列名和值指定。列表中未提到的任何列都将设置为 null。只有对于行级 BEFORE INSERTUPDATE 触发器而言,返回修改后的行才有意义,对于该触发器,将插入修改后的行,而不是在 $NEW 中给出的行;或者对于行级 INSTEAD OF INSERTUPDATE 触发器,返回的行用作 INSERT RETURNINGUPDATE RETURNING 子句的源数据。在行级 BEFORE DELETEINSTEAD 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 FUNCTION trigfunc_modcount('modcnt');

请注意,触发器函数本身不知道列名称;这是由触发器参数提供的。这使得触发器函数可以与不同的表重复使用。