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

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

当事件触发器关联的事件在它被定义的数据库中发生时,事件触发器就会被触发。当前支持的事件有 loginddl_command_startddl_command_endtable_rewritesql_drop。未来版本可能会添加对其他事件的支持。

38.1.1. login #

当一个已认证的用户登录系统时,会发生 login 事件。此事件的触发器过程中任何错误都可能阻止用户成功登录系统。此类错误可以通过在连接字符串或配置文件中将 event_triggers 设置为 false 来规避。或者,您可以以单用户模式重启系统(因为事件触发器在此模式下是禁用的)。有关使用单用户模式的详细信息,请参阅 postgres 参考页。 login 事件在备用服务器上也会触发。为防止服务器变得不可访问,此类触发器在备用服务器上运行时必须避免向数据库写入任何内容。另外,建议避免在 login 事件触发器中执行耗时查询。请注意,例如,在 psql 中取消连接不会取消正在进行的 login 触发器。

有关如何使用 login 事件触发器的示例,请参阅 第 38.5 节

38.1.2. ddl_command_start #

在 DDL 命令执行之前,会发生 ddl_command_start 事件。在此上下文中,DDL 命令包括:

  • CREATE

  • ALTER

  • DROP

  • COMMENT

  • GRANT

  • IMPORT FOREIGN SCHEMA

  • REINDEX

  • REFRESH MATERIALIZED VIEW

  • REVOKE

  • SECURITY LABEL

在执行 SELECT INTO 命令之前,也会发生 ddl_command_start,因为这等同于 CREATE TABLE AS

例外情况是,此事件不会针对以下共享对象的 DDL 命令触发:

  • databases

  • roles (role definitions and role memberships)

  • tablespaces

  • parameter privileges

  • ALTER SYSTEM

此事件也不会针对事件触发器本身的命令触发。

在事件触发器触发之前,不会执行检查以确定受影响的对象是否存在。

38.1.3. ddl_command_end #

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

38.1.4. sql_drop #

对于任何删除数据库对象的 DDL 操作,在 ddl_command_end 事件触发器之前,会发生 sql_drop 事件。请注意,除了显而易见的 DROP 命令之外,一些 ALTER 命令也可能触发 sql_drop 事件。

要列出已被删除的对象,请使用 sql_drop 事件触发器代码中的集合返回函数 pg_event_trigger_dropped_objects()(请参阅 第 9.30 节)。请注意,触发器在对象已从系统目录中删除后执行,因此无法再查找它们。

38.1.5. table_rewrite #

在执行 ALTER TABLEALTER TYPE 命令的某些操作重写表之前,会发生 table_rewrite 事件。虽然有其他控制语句可用于重写表,例如 CLUSTERVACUUM,但 table_rewrite 事件不会由它们触发。要查找被重写的表的 OID,请使用函数 pg_event_trigger_table_rewrite_oid();要发现重写的原因,请使用函数 pg_event_trigger_table_rewrite_reason()(请参阅 第 9.30 节)。

38.1.6. 废弃事务中的事件触发器 #

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

38.1.7. 创建事件触发器 #

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

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

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

提交更正

如果您在文档中发现任何不正确之处、与您对特定功能的体验不符或需要进一步说明的内容,请使用 此表格 报告文档问题。