今天在项目中有一个需求,根据待出库数量大于0来筛选数据,但是问题是待出库数量在pg数据库表中并没有对应的字段,没有办法直接当作graphql查询条件。于是就引出了生成列这个概念。
1.什么是生成列
生成列或计算列对列的作用就像视图对表的作用一样。PostgreSQL 对计算列使用术语“生成”列。该列的值始终是从表中的其他列计算或生成的。生成的列可以是虚拟的或存储的。虚拟列的值是在查询期间动态计算的,它们不会占用存储空间。已存储的列的值已预先计算并存储为表数据的一部分。
2.怎么创建生成列
这里以待出库数量为例创建生成列
2.1创建函数用于计算待出库数量
CREATE OR REPLACE FUNCTION public.get_stay_out_count(prd_count integer, detail_id integer)
RETURNS integer
LANGUAGE plpgsql
IMMUTABLE
AS $function$
declare outed_count int4;
BEGIN
outed_count = (select sum(out_count) from prd_outstorage_detail where prd_outstorage_detail.contract_detail_id = detail_id);
if (outed_count is null) then
outed_count=0;
end if;
return (prd_count - outed_count);
END;
$function$
;
get_stay_out_count(prd_count integer, detail_id integer)
其中get_stay_out_count
为函数名,括号内prd_count
为参数名称 integer
为参数类型。
IMMUTABLE,表示该函数不能修改数据库并且对于给定的参数值总是会返回相同的值。也就是说,它不会做数据库查找或者使用没有在其参数列表中直接出现的信息。如果给定合格选项,任何用全常量参数对该函数的额调用可以立刻用该函数值替换。
language选择plpgsql还是sql详见POSTGRESQL函数中语言SQL和语言PLPGSQL的区别。
declare用于声明一个局部变量。
BEGIN到END之间为函数体,用于实现该函数的功能。
2.2 创建生成列
ALTER TABLE public.prd_contract_detail ADD saty_out_count int4 null generated always AS (get_stay_out_count(prd_count, id)) stored;
使用alter在已存在的表中创建生成列,generated always AS (函数名(参数, 参数)) stored
为创建生成列的固定语法。
注意:
generated always AS (函数名(参数, 参数)) stored
中包裹函数的小括号不能去掉,否则会创建失败!!!