PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

F.41. spi — 服务器编程接口的特性/示例 #

F.41.1. refint — 实现引用完整性的函数
F.41.2. autoinc — 自增字段的函数
F.41.3. insert_username — 跟踪谁修改了表的函数
F.41.4. moddatetime — 跟踪最后修改时间的函数

spi 模块提供多个使用 服务器编程接口(SPI)与触发器的可运行示例。这些函数本身有一定价值,而作为可按自己需求修改的示例,它们更加有用。这些函数足够通用,可以用于任何表,但在创建触发器时你必须指定表名与字段名(如下所述)。

下面描述的每组函数都以可单独安装的扩展形式提供。

F.41.1. refint — 实现引用完整性的函数 #

check_primary_key() 与 check_foreign_key() 用于检查外键约束。(这一功能早已被内置的外键机制取代,但该模块作为示例仍然有用。该模块将在 PostgreSQL 20 中被移除。)

Note

refint 要求使用 安全的模式使用模式,并且要求等值操作符命名为 = 的数据类型。

check_primary_key() 检查引用表。使用时,在引用其他表的表上创建使用该函数的 AFTER INSERT OR UPDATE 触发器。作为触发器参数指定:构成外键的引用表列名、被引用表的名称,以及构成主键/唯一键的被引用表列名。要处理多个外键,请为每个引用各创建一个触发器。

Note

传给 check_primary_key() 的被引用表名与列名参数会按原样复制到内部生成的 SQL 语句中,因此用户必须在 CREATE TRIGGER 命令中按需为它们加上双引号。关于 SQL 标识符加引号的更多信息,请参见 Section 4.1.1。反过来,引用表列名参数不应加双引号。下面是正确使用 check_primary_key() 的模拟示例:

CREATE TRIGGER mytrigger
AFTER INSERT OR UPDATE ON referencing_table
FOR EACH ROW EXECUTE PROCEDURE
check_primary_key (
    'column A', 'column B',         -- referencing table columns
    'myschema."referenced table"',  -- referenced table
    '"column A"', '"column B"'      -- referenced table columns
);

check_foreign_key() 检查被引用表。使用时,在被其他表引用的表上创建使用该函数的 AFTER DELETE OR UPDATE 触发器。作为触发器参数指定:函数需要执行检查的引用表数量、发现引用键时采取的动作(cascade — 删除引用行;restrict — 若引用键存在则中止事务;setnull — 将引用键字段设为空)、构成主键/唯一键的被引用表列名,然后是引用表名与列名(按第一个参数指定的引用表数量重复相应次数)。请注意,主键/唯一键列应标记为 NOT NULL,并且应有唯一索引。

Note

传给 check_foreign_key() 的引用表名与列名参数会按原样复制到内部生成的 SQL 语句中,因此用户必须在 CREATE TRIGGER 命令中按需为它们加上双引号。关于 SQL 标识符加引号的更多信息,请参见 Section 4.1.1。反过来,被引用表列名参数不应加双引号。下面是正确使用 check_foreign_key() 的模拟示例:

CREATE TRIGGER mytrigger
AFTER DELETE OR UPDATE ON referenced_table
FOR EACH ROW EXECUTE PROCEDURE
check_foreign_key (
    1,                              -- number of referencing tables
    'cascade',                      -- action
    'column A', 'column B',         -- referenced table columns
    'myschema."referencing table"', -- referencing table
    '"column A"', '"column B"'      -- referencing table columns
);

请注意,如果这些触发器从另一个 BEFORE 触发器中执行,它们可能意外失败。例如,如果用户插入 row1,然后 BEFORE 触发器插入 row2 并调用带有 check_foreign_key() 的触发器,check_foreign_key() 函数将看不到 row1 并失败。

refint.example 中有示例。

F.41.2. autoinc — 自增字段的函数 #

autoinc() 是一个把序列的下一个值存入整数字段的触发器。它与内置的“serial 列”特性有部分重叠,但并不相同。仅当该字段的值最初为零或空(在插入或更新该行的 SQL 语句生效之后)时,触发器才会替换该字段的值。此外,如果序列的下一个值为零,nextval() 会被再次调用以获得非零值。

使用时,创建使用该函数的 BEFORE INSERT(或可选的 BEFORE INSERT OR UPDATE)触发器。指定两个触发器参数:要修改的整数列的名称,以及提供值的序列对象的名称。(实际上,如果你想更新多个自增列,可以指定任意多对这样的名称。)

autoinc.example 中有一个示例。

F.41.3. insert_username — 跟踪谁修改了表的函数 #

insert_username() 是一个把当前用户名存入文本字段的触发器。这有助于跟踪表内某一行最后一次被谁修改。

使用时,创建使用该函数的 BEFORE INSERT 与/或 UPDATE 触发器。指定单个触发器参数:要修改的文本列的名称。

insert_username.example 中有一个示例。

F.41.4. moddatetime — 跟踪最后修改时间的函数 #

moddatetime() 是一个把当前时间存入 timestamp 字段的触发器。这有助于跟踪表内某一行最后的修改时间。

使用时,创建使用该函数的 BEFORE UPDATE 触发器。指定单个触发器参数:要修改的列的名称。该列必须是 timestamp 或 timestamp with time zone 类型。

moddatetime.example 中有一个示例。