9.3 9.4 9.5 9.6 10 11 12 13 14 15 Current(16) 17
问题报告 纠错本页面
5.3. 生成列
上一页 上一级 第 5 章 数据定义起始页 下一页

5.3. 生成列 #

生成的列是一个特殊的列,它总是从其他列计算而来。因此说,它对于列就像视图对于表一样。生成列有两种:存储列和虚拟列。 存储生成列在写入(插入或更新)时计算,并且像普通列一样占用存储空间。虚拟生成列不占用存储空间并且在读取时进行计算。 如此看来,虚拟生成列类似于视图,存储生成列类似于物化视图(除了它总是自动更新之外)。 PostgreSQL目前只实现了存储生成列。

建立一个生成列,在 CREATE TABLE中使用 GENERATED ALWAYS AS 子句, 例如:

CREATE TABLE people (
 ...,
 height_cm numeric,
 height_in numeric GENERATED ALWAYS AS (height_cm / 2.54) STORED
);

必须指定关键字 STORED 以选择存储类型的生成列。更多细节请参见 CREATE TABLE

生成列不能被直接写入. 在INSERTUPDATE 命令中, 不能为生成列指定值, 但是可以指定关键字DEFAULT

考虑列缺省情况和生成列之间的差异。 如果没有提供其他值,列缺省情况下在行被首次插入时计算一次;生成列则在行每次改变时进行更新,并且不能被取代。 列缺省情况下不能引用表的其他列;生成表达式通常会这样做。 列缺省情况下可以使用易失性函数,例如random()或引用当前时间函数; 而对于生成列这是不允许的。

对于生成列和涉及生成列的表的定义,有以下几个限制:

  • 生成表达式只能使用不可变函数,不能使用子查询,也不能以任何方式引用 当前行以外的内容。

  • 生成表达式不能引用另一个生成列。

  • 生成表达式不能引用系统列,除了tableoid

  • 生成列不能有列默认值或标识定义。

  • 生成列不能是分区键的一部分。

  • 外部表可以有生成列。详见CREATE FOREIGN TABLE

  • 关于继承和分区:

    • 如果父列是生成列,则其子列也必须是生成列;然而,子列可以有不同的 生成表达式。在插入或更新行时实际应用的生成表达式是与行实际所在表 关联的表达式。(这与列默认值的行为不同:对于列默认值,应用的是查 询中指定的表关联的默认值。)

    • 如果父列不是生成列,则其子列也不能是生成列。

    • 对于继承表,如果在CREATE TABLE ... INHERITS 中定义子列时没有包含任何GENERATED子句, 那么其GENERATED子句将自动从父列复制。 ALTER TABLE ... INHERIT将要求父列和子列在 生成状态上已经匹配,但不会要求它们的生成表达式匹配。

    • 同样地,对于分区表,如果在CREATE TABLE ... PARTITION OF中定义子列时没有包含任何GENERATED 子句,那么其GENERATED子句将自动从父列复制。 ALTER TABLE ... ATTACH PARTITION将要求父列和 子列在生成状态上已经匹配,但不会要求它们的生成表达式匹配。

    • 在多重继承的情况下,如果一个父列是生成列,那么所有父列都必须是 生成列。如果它们的生成表达式不完全相同,则必须明确指定子列的期望 表达式。

对于使用生成列,需要考虑其他事项。

  • 生成列的访问权限与其基础列的访问权限是分开维护的。因此,可以安排 某个特定角色可以读取生成列,但不能读取基础列。

  • 从概念上讲,生成列是在BEFORE触发器运行之后更新的。 因此,在BEFORE触发器中对基础列所做的更改将反映在 生成列中。但相反,在BEFORE触发器中访问生成列是 不允许的。

  • 生成列会被逻辑复制跳过,且不能在CREATE PUBLICATION 的列列表中指定。


上一页 上一级 下一页
5.2. 默认值 起始页 5.4. 约束

AltStyle によって変換されたページ (->オリジナル) /