PostgreSQL中的计算/计算/虚拟/派生列

Mik*_*ain 92 postgresql materialized-views calculated-columns sql-view generated-columns

PostgreSQL是否支持计算/计算列,如MS SQL Server?我在文档中找不到任何内容,但由于此功能包含在许多其他DBMS中,我认为我可能会遗漏某些内容.

例如:http://msdn.microsoft.com/en-us/library/ms191250.aspx

Erw*_*ter 112

不支持Postgres 11 生成的列 - 如SQL标准中所定义,并由包括DB2,MySQL和Oracle在内的一些RDBMS实现.也不是SQL Server 的类似"计算列".

Postgres 12的主要作者Peter Eisentraut 正在开发该功能.

现在,您可以使用属性表示法()查看函数,该函数看起来和工作方式非常类似于虚拟生成列.由于历史原因,这在Postgres中存在一点语法怪异,恰好适合这种情况.这个相关的答案有代码示例:STORED

但是,表达式(看起来像一列)不包含在a中VIRTUAL.您必须明确地列出它.

也可以使用匹配的表达式索引支持 - 只要函数是VIRTUAL.喜欢:

CREATE TABLE tbl (
  int1    int
, int2    int
, product bigint GENERATED ALWAYS AS (int1 * int2) STORED
);
Run Code Online (Sandbox Code Playgroud)

备择方案

或者,您可以使用a实现类似的功能tbl.col,可选择与表达式索引相结合.然后SELECT * FROM tbl可以包括生成的列.

"持久"计算列可以用功能相同的方式用触发器实现.

物化观点是一个密切相关的概念,自Postgres 9.3以来实施.
在早期版本中,可以手动管理MV.

  • 该功能目前正在开发中:https://commitfest.postgresql.org/16/1443/ (4认同)

dan*_*man 27

是的你可以!! 解决方案应该简单,安全,高效......

我是postgresql的新手,但似乎你可以通过使用表达式索引创建计算列,与视图配对(视图是可选的,但会使生活变得更容易).

假设我的计算是md5(some_string_field),那么我创建索引为:

CREATE INDEX some_string_field_md5_index ON some_table(MD5(some_string_field));
Run Code Online (Sandbox Code Playgroud)

现在,任何作用的查询MD5(some_string_field)都将使用索引而不是从头开始计算.例如:

SELECT MAX(some_field) FROM some_table GROUP BY MD5(some_string_field);
Run Code Online (Sandbox Code Playgroud)

您可以通过解释来查看.

但是,此时您依赖于表的用户知道如何构造列.为了简化生活,您可以VIEW在原始表的增强版本上创建,将计算值添加为新列:

CREATE VIEW some_table_augmented AS 
   SELECT *, MD5(some_string_field) as some_string_field_md5 from some_table;
Run Code Online (Sandbox Code Playgroud)

现在任何使用的查询some_table_augmented都可以使用some_string_field_md5而不用担心它是如何工作的......它们只是获得了良好的性能.该视图不会复制原始表中的任何数据,因此它在内存方面和性能方面都很好.但请注意,您无法更新/插入视图,只能进入源表,但如果您真的需要,我相信您可以使用规则将插入和更新重定向到源表(我可能在最后一点上错了我自己从未尝试过).

编辑:似乎查询涉及竞争索引,计划程序引擎有时可能根本不使用表达式索引.选择似乎取决于数据.


Elm*_*mer 13

一种方法是使用触发器!

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();
Run Code Online (Sandbox Code Playgroud)

在更新或插入行之前触发触发器.它会更改我们要计算NEW记录的字段,然后返回该记录.

  • 尝试`插入计算(一个)值(1);插入到计算(一个)值(4)中;犯罪; select * from calculate;` 将自动计算 `two` 列的值! (2认同)

Luk*_*zda 8

PostgreSQL 12支持生成的列:

PostgreSQL 12 Beta 1发布了!

生成的列

PostgreSQL 12允许创建生成的列,并使用其他列的内容通过表达式来计算其值。此功能提供了存储的生成的列,这些列在插入和更新时计算并保存在磁盘上。仅当将列作为查询的一部分读取时才计算的虚拟生成列尚未实现。


生成的列

生成的列是特殊列,始终从其他列计算得出。因此,表的视图就是列。

CREATE TABLE people (
    ...,
    height_cm numeric,
    height_in numeric GENERATED ALWAYS AS (height_cm * 2.54) STORED
);
Run Code Online (Sandbox Code Playgroud)

db <> fiddle演示