第四十七章. 触发器

内容
创建触发器
与触发器管理器交互
数据改变的可视性
例子
Postgres 拥有多种客户接口,象Perl,Tcl,Python 和 C,还有两种 过程语言 (PL).同样也可能把 C 函数的调用作为触发器的动作.要注意当前版本还不支持语句级(STATEMENT-level)的触发器事件.目前你可以在 INSERT,DELETE 或 UPDATE 一条记录上声明 BEFORE 或 AFTER (之前或之后)作为触发器事件.

创建触发器

如果发生了触发器事件,触发器管理器(由执行器调用)初始化全局结构 TriggerData *CurrentTriggerData (下面描述)并调用触发器函数来操作事件.

触发器函数必须作为一个没有参数并且返回 opaque 的函数在创建触发器之前创建.

创建触发器的语法如下:

CREATE TRIGGER trigger [ BEFORE | AFTER ] [ INSERT | DELETE | UPDATE [ OR ... ] ]
    ON relation FOR EACH [ ROW | STATEMENT ]
    EXECUTE PROCEDURE procedure
     (args);
这里的参数是:
trigger
如果你想删除触发器,那么这是所使用的触发器的名称.它被当做 DROP TRIGGER 命令的一个参数.
BEFORE, AFTER
决定函数是在事件之前还是之后调用.
INSERT, DELETE, UPDATE
命令的下一元素决定在什么事件上触发该函数.多个事件可以用 OR 分隔声明.
relation
关系名,决定该事件应用于哪个表.
ROW, STATEMENT
FOR EACH 子句决定该触发器是为每个受影响的行触发还是在整个语句完成之前(或之后)触发.
procedure
过程名就是调用的 C 函数.
args
参数是放在 CurrentTriggerData 结构里面传给函数的.传递参数给函数的目的是为了允许类似要求的不同的触发器调用同样的函数.

 

 
 
 

同样,函数可以被用于触发不同的关系(这些函数被命名为"通用触发器函数")。

做为使用上面两个特性的例子,可以有一个通用函数把两个字段名称作为参数:把当前用户作为一个参数而把当前时标做为另一个参数.这样就允许我们在 INSERT 事件上写一个触发器来自动跟踪一个事务表里的记录的创建.如果用于一个 UPDATE 事件,同样我们可以当 "最后更新"(last updated)函数来用.

触发器函数返回 HeapTuple 给调用它的执行器.这个返回在那些在 INSERT,DELETE 或 UPDATE 操作之后执行的触发器上被忽略,但它允许那些 BEFORE 触发器用来: 注意,CREATE TRIGGER 句柄将不进行任何初始化工作.这一点将在以后进行修改.同样,如果多于一个触发器为同样的事件定义在同样的关系上,触发器触发的顺序将不可预料.这一点以后也会修改.

如果一个触发器函数执行 SQL-查询(使用 SPI)那么这些查询可能再次触发触发器.这就是所谓的嵌套触发器.对嵌套触发器的嵌套深度没有显式的限制.

如果一个触发器是被 INSERT 触发并且插入一个新行到同一关系中,然后该触发器将被再次触发.目前对这种情况没有提供任何同步(等)的措施,这一点也可能会修改.目前,回归测试里有一个函数 funny_dup17() 使用了一些技巧避免对自身的递归(嵌套)调用...