Postgresql 中文操作指南

40.1. Overview of Event Trigger Behavior #

每当与其关联的事件在定义它的数据库中发生时,事件触发器就会执行。目前,仅支持 ddl_command_startddl_command_endtable_rewritesql_drop 事件。未来版本中可能会添加对其他事件的支持。

ddl_command_start 事件在 CREATEALTERDROPSECURITY LABELCOMMENTGRANTREVOKE 命令执行前发生。在事件触发器执行前,不会执行任何检查以判断受影响的对象是否存在。但是,作为一个例外,对于针对共享对象(数据库、角色和表空间)的 DDL 命令或针对事件触发器自身的命令,此事件不会发生。事件触发器机制不支持此类对象类型。ddl_command_start 也在 SELECT INTO 命令执行前发生,因为这相当于 CREATE TABLE AS

ddl_command_end 事件发生在执行此组命令之后的瞬间。要获得所发生的 DDL 操作的更多详细信息,请使用 ddl_command_end 事件触发器代码的 set-returning 函数 pg_event_trigger_ddl_commands() (请参阅 Section 9.29)。请注意,触发器是在动作发生后(但在事务提交之前)触发的,因此系统目录可以读取为已更改。

在发生释放数据库对象的任何操作的 ddl_command_end 事件触发器之前,会发生 sql_drop 事件。如需列出已被释放的对象,请从 sql_drop 事件触发器代码 (详见 Section 9.29) 使用返回集合的功能 pg_event_trigger_dropped_objects()。注意,该触发器在从系统目录中删除对象后执行,因此不再能够查找它们。

table_rewrite 事件在使用 ALTER TABLEALTER TYPE 命令中的部分操作对表重新写入之前发生。虽然可用其他控制语句(例如 CLUSTERVACUUM)对表重新写入,但 table_rewrite 事件不会触发它们。

事件触发器(以及其他函数)无法在已中止的事务中执行。因此,如果 DDL 命令因某个错误而失败,则任何关联的 ddl_command_end 触发器都无法执行。相反,如果 ddl_command_start 触发器因某个错误而失败,则后续事件触发器将无法执行,并且系统不会尝试执行命令本身。同样,如果 ddl_command_end 触发器因某个错误而失败,则 DDL 语句的效果将回滚,就像在包含事务中止的任何其他情况下一样。

有关事件触发机制支持的命令完整列表,请参阅 Section 40.2

事件触发器使用 CREATE EVENT TRIGGER 命令创建。为了创建事件触发器,您首先必须使用特殊返回类型 event_trigger 创建一个函数。此函数不需要(并且可能不)返回值;返回类型仅用作指示该函数应作为事件触发器调用的信号。

如果针对特定事件定义了多个事件触发器,则按事件触发器名称以字母顺序执行这些事件触发器。

触发器定义也可以指定 WHEN 条件,这样,例如,仅针对用户希望拦截的特定命令触发 ddl_command_start 触发器。这类触发器的常用方法是限制用户可以执行的 DDL 操作范围。