PostgreSQL是否支持计算/计算列,如MS SQL Server?我在文档中找不到任何内容,但由于此功能包含在许多其他DBMS中,我认为我可能会遗漏一些内容。
答案 0 :(得分:89)
不支持Postgres 11 生成的列 - 如SQL标准中所定义,并由包括DB2,MySQL和Oracle在内的某些RDBMS实现。也不是SQL Server的类似“计算列”。
该特征是in development for Postgres 12,主要作者Peter Eisentraut。
目前,您可以使用功能模拟属性符号(tbl.col
)外观和工作原理很像虚拟生成列。由于历史原因,这在Postgres中存在一些语法怪异,恰好适合这种情况。此相关答案包含代码示例:
表达式(看起来像一列)不包含在SELECT * FROM tbl
中。您必须明确地列出它。
也可以使用匹配的表达式索引支持 - 只要函数为IMMUTABLE
。像:
CREATE FUNCTION col(tbl) ... AS ... -- your computed expression here
CREATE INDEX ON tbl(col(tbl));
或者,您可以使用VIEW
实现类似的功能,可选择与表达式索引结合使用。然后SELECT *
可以包含生成的列。
“持久”计算列可以使用triggers以功能相同的方式实现。
Materialized views是一个密切相关的概念,implemented since Postgres 9.3 在早期版本中,可以手动管理MV。
答案 1 :(得分:23)
是的,你可以!! 解决方案应该简单,安全,高效......
我是postgresql的新手,但似乎你可以使用expression index创建计算列,并与view配对(视图是可选的,但会让生活变得更轻松)。
假设我的计算是md5(some_string_field)
,那么我将索引创建为:
CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));
现在,任何作用于MD5(some_string_field)
的查询都将使用索引,而不是从头开始计算。例如:
SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);
您可以使用explain进行检查。
但是,此时您依赖于表的用户知道如何构建列。为了简化生活,您可以在原始表的增强版本上创建VIEW
,将计算值添加为新列:
CREATE VIEW some_table_augmented AS
SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;
现在,使用some_table_augmented
的任何查询都可以使用some_string_field_md5
而无需担心它是如何工作的......它们只是获得了良好的性能。该视图不会复制原始表中的任何数据,因此它在内存方面和性能方面都很好。但请注意,您无法更新/插入视图,只能进入源表,但如果您真的需要,我相信您可以使用rules将插入和更新重定向到源表(我可能错了)最后一点,因为我自己从未尝试过。)
编辑:似乎查询涉及竞争索引,计划程序引擎有时可能根本不使用表达式索引。选择似乎取决于数据。
答案 2 :(得分:12)
执行此操作的一种方法是使用触发器!
CREATE TABLE computed(
one SERIAL,
two INT NOT NULL
);
CREATE OR REPLACE FUNCTION computed_two_trg()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $BODY$
BEGIN
NEW.two = NEW.one * 2;
RETURN NEW;
END
$BODY$;
CREATE TRIGGER computed_500
BEFORE INSERT OR UPDATE
ON computed
FOR EACH ROW
EXECUTE PROCEDURE computed_two_trg();
在更新或插入行之前触发触发器。它会更改我们要计算NEW
记录的字段,然后返回该记录。
答案 3 :(得分:0)
我有一个有效的代码并且使用了计算的术语,我不是在postgresSQL纯粹的,我们在PADB上运行
这是如何使用
create table some_table as
select category,
txn_type,
indiv_id,
accum_trip_flag,
max(first_true_origin) as true_origin,
max(first_true_dest ) as true_destination,
max(id) as id,
count(id) as tkts_cnt,
(case when calculated tkts_cnt=1 then 1 else 0 end) as one_way
from some_rando_table
group by 1,2,3,4 ;
答案 4 :(得分:0)
PostgreSQL 12支持生成的列:
PostgreSQL 12 Beta 1 Released!
生成的列
PostgreSQL 12允许创建生成的列,并使用其他列的内容使用表达式来计算其值。此功能提供了存储的生成的列,这些列是在插入和更新时计算的,并保存在磁盘上。虚拟的生成的列(仅当将列作为查询的一部分读取时才计算)尚未实现。 >
生成的列是一个特殊列,总是从其他列计算得出。因此,表的视图就是列。
CREATE TABLE people (
...,
height_cm numeric,
height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);
答案 5 :(得分:-2)
好吧,不确定这是否是您的意思,但Posgres通常支持“虚拟” ETL语法。 我在表中创建了一个空列,然后需要根据行中的值通过计算的记录来填充它。
UPDATE table01
SET column03 = column01*column02; /*e.g. for multiplication of 2 values*/
答案 6 :(得分:-4)
具有Check约束的轻量级解决方案:
CREATE TABLE example (
discriminator INTEGER DEFAULT 0 NOT NULL CHECK (discriminator = 0)
);