# 5.3.生成的列

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

要创建生成的列,请使用始终生成条款创建表格,例如:

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

关键词存储必须指定才能选择生成列的存储类型。看见创建表格更多细节。

生成的列不能直接写入。在里面插入使现代化命令时,不能为生成的列指定值,但必须指定关键字违约可以指定。

考虑具有默认列和生成列的列之间的差异。如果没有提供其他值,则在第一次插入行时对列默认值求值一次;只要行发生更改,生成的列就会更新,并且不能被重写。列默认值不能引用表中的其他列;世代表达式通常会这样做。例如,列默认值可以使用volatile函数随机的或引用当前时间的函数;生成的列不允许这样做。

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

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

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

  • 生成表达式不能引用系统列,除非片状.

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

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

  • 外部表可以生成列。看见创建外部表详细信息。

  • 对于继承:

    • 如果父列是生成的列,则子列也必须是使用相同表达式生成的列。在子列的定义中,去掉生成子句,因为它将从父级复制。

    • 在多重继承的情况下,如果一个父列是生成的列,那么所有父列都必须是生成的列,并且具有相同的表达式。

    • 如果父列不是生成的列,则子列可以定义为生成的列,也可以定义为非生成的列。

    其他注意事项适用于生成列的使用。

  • 生成的列与它们的基础基列分开维护访问权限。因此,可以对其进行安排,以便特定角色可以从生成的列中读取,但不能从底层的基本列中读取。

  • 从概念上讲,生成的列在之前触发器已经启动。因此,对之前触发器将反映在生成的列中。但相反,它不允许访问中生成的列之前触发器。