生成列(Generated Column)是一种其取值始终依据同一行内其他列动态计算而得的特殊字段。它在列层级所起到的作用,类似于视图在表层级所扮演的角色。生成列主要分为两类:存储型(stored)与虚拟型(virtual)。存储型生成列在数据写入(插入或更新)时计算并将结果持久化在磁盘上,占用实际物理存储;虚拟型生成列则不占用任何物理磁盘空间,在每次被读取查询时动态实时求值。因此,虚拟型生成列类似于轻量视图,而存储型生成列则类似于自动刷新的物化视图。
在 CREATE TABLE 中使用 GENERATED ALWAYS AS 子句声明生成列:
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm / 2.54)
);
在默认情况下,生成列属于虚拟型。可以通过显式添加关键字 VIRTUAL 或 STORED 进行明确指定。详见 CREATE TABLE。
生成列不允许直接被外部赋值写入。在执行 INSERT 或 UPDATE 时,不能为生成列传递具体数据,但允许指定关键字 DEFAULT。
比较带默认值的列与生成列的区别:默认值仅在初次插入且未传值时单次求值,后续行更新不会联动改变默认值,且允许被显式覆盖;生成列则随整行数据的变更时刻自动联动刷新,不可被手动覆盖。默认值不能引用同表的其他列,而生成列的计算表达式通常正是基于其他列展开。默认值可以使用非确定性函数(如 random() 或获取当前时间的函数),但生成列严格禁止使用易失函数。
定义生成列时必须遵守以下限制:
生成表达式只能使用不可变(IMMUTABLE)函数,严禁包含子查询,且除当前物理行之外不得以任何形式引用外部数据。
生成表达式不得引用另一个生成列。
生成表达式不得引用系统内部列(除 tableoid 之外)。
虚拟型生成列不得使用用户自定义类型,且其生成表达式不得引用自定义函数或类型,只能使用系统内置函数与类型。
生成列不得再声明普通列默认值或标识列定义。
生成列不能充当表分区键的组成部分。