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

40.1. 事件触发器行为概述 #

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

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

在执行同一组命令之后,ddl_command_end 事件就会发生。要获取有关发生的 DDL 操作的更多详细信息,请从 ddl_command_end 事件触发器代码中使用返回集合的函数 pg_event_trigger_ddl_commands()(请参阅 第 9.29 节)。请注意,触发器在操作发生后(但在事务提交之前)触发,因此可以将系统目录读为已更改。

对于任何删除数据库对象的 ddl_command_end 事件触发器操作,sql_drop 事件都会在该触发器之前发生。要列出已删除的对象,请从 sql_drop 事件触发器代码中使用返回集合的函数 pg_event_trigger_dropped_objects()(请参阅 第 9.29 节)。请注意,该触发器在对象从系统目录中删除后执行,因此无法再查找它们。

ALTER TABLEALTER TYPE 命令的某些操作重写表之前,table_rewrite 事件就会发生。虽然可以使用其他控制语句(如 CLUSTERVACUUM)重写表,但 table_rewrite 事件不会被它们触发。

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

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

事件触发器使用命令 CREATE EVENT TRIGGER 创建。为了创建一个事件触发器,你必须首先创建一个具有特殊返回类型 event_trigger 的函数。此函数不需要(也不可能)返回一个值;返回类型仅仅作为函数将被调用为事件触发器的信号。

如果为某个特定事件定义了多个事件触发器,它们将按触发器名称按字母顺序触发。

触发器定义还可以指定一个 WHEN 条件,以便例如,ddl_command_start 触发器只能针对用户希望拦截的特定命令触发。此类触发器的常见用法是限制用户可以执行的 DDL 操作范围。