计算列通过列定义中包含的表达式从其他列生成的数据。
存储计算列在插入或更新行时进行计算,并将结果值存储在主索引中,类似于非计算列。
JSONB
计算列在与列或二级索引一起使用时特别有用。
可以在计算列上创建二级索引,这在经常对表进行排序时特别有用,以下有示例说明。
JSONB
列用于存储半结构化JSONB
数据。计算列允许以下用例:一个包含一个列和一个JSONB
列的表payload
,其主键是根据该payload
列的一个字段计算得出的,以下有示例说明。
计算列:
虚拟计算列:
FAMILY
定义、CHECK
约束或FOREIGN KEY
约束的一部分。要定义存储计算列,请使用以下语法:
column_name <type> as (<expr>) stored
要定义虚拟计算列,请使用以下语法:
column_name <type> as (<expr>) virtual
范围 | 描述 |
---|---|
{index_name} | 计算列的名称。 |
<type> | 计算列的数据类型。 |
<expr> | 用于计算列值的不可变表达式。 |
stored | 计算列与其他列一起存储。 |
virtual | 计算列是虚拟的,这意味着列数据不存储在表的主索引中。 |
create table cust_info (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tell_no string,
first_name string,
last_name string,
all_name string AS (concat(first_name, ' ', last_name)) stored,
card_no string
);
insert into cust_info (first_name, last_name) values
('liu', 'dehua'),
('zhang', 'zijian'),
('ren', 'xianqi');
table cust_info;
id | tell_no | first_name | last_name | all_name | card_no
---------------------------------------+---------+------------+-----------+--------------+----------
1ff89b14-d27e-4ad8-b6e7-1d14f6a2dad6 | NULL | liu | dehua | liu dehua | NULL
a4413c62-3f99-4bf3-b0a2-2f9770887304 | NULL | zhang | zijian | zhang zijian | NULL
b17080f0-4a73-4364-966f-89e29937a3fc | NULL | ren | xianqi | ren xianqi | NULL
该all_name
列是根据first_name
和last_name
列计算的
创建一个包含一JSONB
列和一个存储的计算列的表:
此示例显示如何添加具有强制类型的存储计算列:
create table json_test (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
jsoninfor JSONB
);
insert into json_test (jsoninfor) VALUES ('{"aml": "111.11"}');
alter table json_test ADD COLUMN aml DECIMAL AS ((jsoninfor->>'aml')::DECIMAL) stored;
select * from json_test;
id | jsoninfor | aml
---------------------------------------+-------------------+---------
8d3968da-ed51-42f0-9446-13f447da4d53 | {"aml": "111.11"} | 111.11
在此示例中,创建一个包含JSONB
列和虚拟计算列的表:
create table custinfo (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
testdata jsonb,
all_name string AS (concat_ws(' ',testdata->>'firstName', testdata->>'lastName')) VIRTUAL
);
insert into custinfo (testdata) VALUES
('{"id": "d11111", "firstName": "Arthur", "lastName": "Read", "school": "PVPHS", "credits": 100, "sports": "none"}'),
('{"firstName": "Buster", "lastName": "Bunny", "id": "f92222", "school": "THS", "credits": 24, "clubs": "MUN"}'),
('{"firstName": "Ernie", "lastName": "Narayan", "school" : "Brooklyn Tech", "id": "t00074", "sports": "Track and Field", "clubs": "Chess"}');
select * from custinfo;
id | testdata | all_name
---------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+----------------
308b8137-a20f-43f8-94a8-a66a79dea124 | {"clubs": "MUN", "credits": 24, "firstName": "Buster", "id": "f92222", "lastName": "Bunny", "school": "THS"} | Buster Bunny
613ce51c-b25b-4dec-8958-317d56425a72 | {"credits": 100, "firstName": "Arthur", "id": "d11111", "lastName": "Read", "school": "PVPHS", "sports": "none"} | Arthur Read
e1d9c1e0-0e89-410f-b46e-9ed265466db5 | {"clubs": "Chess", "firstName": "Ernie", "id": "t00074", "lastName": "Narayan", "school": "Brooklyn Tech", "sports": "Track and Field"} | Ernie Narayan
虚拟列all_name
的计算来自testdata
列数据的字段
创建一个表,其中包含虚拟计算列和该列的索引:
create table totalby (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tname STRING,
a decimal,
b decimal,
c decimal,
d decimal,
t_score DECIMAL as (a + b + c + d) VIRTUAL,
index total ( t_score desc)
);
然后,插入几行数据:
insert into totalby (tname, a , b , c , d) values
('zahngsan', 15.111, 14.823, 25.600, 12.400),
('lisi', 0, 15.766, 0, 0),
('wangwu', 14.500, 0, 16.243, 14.563),
('liuliu', 0, 15.453, 0, 0),
('cluo', 11.233, 0, 12.440, 14.116);
现在,使用二级索引运行查询:
select tname,t_score from totalby order by t_score desc;
tname | t_score
-----------+----------
zahngsan | 67.934
wangwu | 45.306
cluo | 37.789
lisi | 15.766
liuliu | 15.453
创建一个表:
create table abc (
a INT NULL,
b INT NULL AS (a * 3) stored,
c INT NULL AS (a + 5) stored,
FAMILY "primary" (a, b, rowid, c)
);
然后,插入一行数据:
insert into abc values (2);
table abc;
a | b | c
----+---+----
2 | 6 | 7
2 | 6 | 7
现在向表中添加另一个虚拟计算列:
alter table abc add column d int AS (a // 2) VIRTUAL;
table abc;
a | b | c | d
----+---+---+----
2 | 6 | 7 | 1
2 | 6 | 7 | 1
数据准备:
create table abc (
a INT NULL,
b INT NULL AS (a * 3) stored,
c INT NULL AS (a + 5) stored,
FAMILY "primary" (a, b, rowid, c)
);
alter table abc add column d int AS (a // 2) stored;
要更改计算列的公式,必须DROP
列,并用ADD
语句重新定义列:
set sql_safe_updates = false;
alter table abc drop column d;
alter table abc add column d int as (a // 4) stored;
set sql_safe_updates = true;
可以使用ALTER TABLE
语句将存储的计算列转换为常规列。
创建一个带有计算列的表:
create table zoos (
id INT PRIMARY KEY,
first_name string,
last_name string,
all_name string AS (CONCAT(first_name, ' ', last_name)) stored
);
表中数据准备
insert into zoos (id, first_name, last_name) values
(10, 'pa', 'hawei'),
(20, 'ma', 'li'),
(30, 'da', 'xinging');
select * from zoos;
id | first_name | last_name | all_name
-----+------------+-----------+-------------
10 | pa | hawei | pa hawei
20 | ma | li | ma li
30 | da | xinging | da xinging
该all_name
列是根据first_name
和last_name
列计算得来的
show columns from zoos;
column_name | data_type | is_nullable | column_default | generation_expression | indices | is_hidden
--------------+-----------+-------------+----------------+------------------------------------+-----------+------------
id | INT8 | false | NULL | | {primary} | false
first_name | STRING | true | NULL | | {} | false
last_name | STRING | true | NULL | | {} | false
all_name | STRING | true | NULL | concat(first_name, ' ', last_name) | {} | false
将计算列all_name
转换为常规列:
alter table zoos alter column all_name drop stored;
检查是否转换成功
show columns from zoos;
column_name | data_type | is_nullable | column_default | generation_expression | indices | is_hidden
--------------+-----------+-------------+----------------+------------------------------------+-----------+------------
id | INT8 | false | NULL | | {primary} | false
first_name | STRING | true | NULL | | {} | false
last_name | STRING | true | NULL | | {} | false
all_name | STRING | true | NULL | | {} | false
重新准备数据
insert into zoos (id, first_name, last_name,all_name) values (40, 'paper', 'tiger', 'This is null');
再次展示数据
select * from zoos;
id | first_name | last_name | all_name
-----+------------+-----------+---------------
10 | pa | hawei | pa hawei
20 | ma | li | ma li
30 | da | xinging | da xinging
40 | paper | tiger | This is null