KingbaseES自动生成列介绍

在KingbaseES中create table语句支持GENERATED column(生成列)。

生成列是一种特别的列类型,它的值基于其他列的值计算得出。因此,生成列之于列,有点像视图之于表的关系。存在两种类型的生成列:存储生成列和虚拟生成列。

存储生成列在数据被写入(插入或更新操作)时进行计算,并且像常规列那样,它们在存储上占据空间。相比之下,虚拟生成列并不占用存储空间,它们的值是在被读取时才计算出来的。从这个角度看,虚拟生成列与视图相似,而存储生成列则类似于物化视图,不同之处在于它们总是自动更新。目前,KingbaseES只支持存储生成列。要创建一个生成列,可以在 CREATE TABLE 语句中使用 GENERATED ALWAYS AS 子句。
例如:

test=# CREATE TABLE score("姓名" varchar(20),"语文" int, "数学" int, "英语" int, "总分" int GENERATED ALWAYS AS ("语文"+"数学"+"英语") STORED);
CREATE TABLE
test=# \d score
                                             数据表 "public.score"
 栏位 |            类型            | 校对规则 | 可空的 |                         预设
------+----------------------------+----------+--------+-------------------------------------------------------
 姓名 | character varying(20 char) |          |        |
 语文 | integer                    |          |        |
 数学 | integer                    |          |        |
 英语 | integer                    |          |        |
 总分 | integer                    |          |        | generated always as ("语文" + "数学" + "英语") stored

test=# insert into score values ('小明',89,99,99);
INSERT 0 1
test=# select * from score ;
 姓名 | 语文 | 数学 | 英语 | 总分
------+------+------+------+------
 小明 |   89 |   99 |   99 |  287
(1 行记录)

test=# insert into score values ('小明',89,99,99,287);
错误:  无法插入到列"总分"
描述:  列"总分"是生成的列.

test=# CREATE TABLE score("姓名" varchar(20),"语文" int, "数学" int, "英语" int, "总分" int GENERATED ALWAYS AS ("语文"+"数学"+"英语") STORED) partition by range ("总分");
错误:  无法在分区键中使用生成的列
第1行... ("语文"+"数学"+"英语") STORED) partition by range ("总分");                                                            ^
描述:  列"总分"是生成的列.

需要注意的是,生成列不能直接接收插入或更新的值。
尽管在 INSERT 或 UPDATE 命令中不能为生成列指定具体的值,使用 DEFAULT 关键字仍然是可行的。
理解列的默认值与生成列之间的区别是重要的:默认值只在行首次插入时计算一次,而生成列则在每次行变动时更新,并且无法被其他值取代。
列的默认值不能引用表中的其他列,而生成列通常会这样做。默认值可以使用易变函数,如random()或当前时间函数,但生成列则不允许这样做。

生成列和包含生成列的表定义还有一些限制:

  • 生成表达式只能使用不可变函数,不能使用子查询,也不能以任何方式引用当前行以外的内容
  • 生成表达式不能引用另一个生成列或系统表(除了 tableoid)
  • 生成列不能设置列默认值或标识定义,也不能作为分区键的一部分
  • 外部表可以包含生成列
  • 不能基于其他生成列定义一个新的生成列

使用生成列时的其他注意事项包括:
生成列具有与其底层基础列不同的访问权限。因此可以设置权限,以便特定角色只能从生成列读取数据,而不是从底层基础列。
从概念上讲,生成列在BEFORE触发器执行后更新,因此 BEFORE 触发器中对基础列所做的更改将反映在生成列中。然而,反过来,在BEFORE触发器中不能访问生成列。

posted @ 2024-03-28 15:32  KINGBASE研究院  阅读(33)  评论(0编辑  收藏  举报