2024年9月26日: PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本:11 / 10 / 9.6 / 9.5 / 9.4 / 9.3

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

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

当经过身份验证的用户登录系统时,就会发生 login 事件。此事件的触发器过程中出现的任何错误都可能阻止成功登录系统。可以通过将 event_triggers 设置为 false(在连接字符串或配置文件中)来解决此类错误。或者,您可以以单用户模式重新启动系统(因为在此模式下事件触发器被禁用)。有关使用单用户模式的详细信息,请参阅 postgres 参考页面。 login 事件也会在备用服务器上触发。为了防止服务器无法访问,此类触发器在备用服务器上运行时必须避免写入任何内容到数据库。此外,建议避免在 login 事件触发器中使用长时间运行的查询。请注意,例如,在 psql 中取消连接不会取消正在进行的 login 触发器。

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

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

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

ALTER TABLEALTER TYPE 命令的一些操作重写表之前,会发生 table_rewrite 事件。虽然还有其他控制语句可用于重写表,例如 CLUSTERVACUUM,但 table_rewrite 事件不会由它们触发。

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

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

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

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

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

提交更正

如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用 此表单 报告文档问题。