PostgreSQL:生成的列

Man*_*ngo 19 postgresql computed-column

PostgreSQL 是否支持生成的列?也称为虚拟列。我不是在谈论IDENTITY

我找不到有关此卓越功能的任何信息,但我知道它在 SQL Server 以及最新版本的 MariaDB 和 MySQL 中可用。

SQL:2003标准中提到了该功能,并且在 2006 年左右在 PostgreSQL 论坛上进行了一些讨论,但我找不到关于此事的任何实质性内容。

有一些关于 SO 的讨论,但它现在已经很老了,所以它很可能已经过时了。

小智 22

不确定这是否是您想要的,但属性表示法row.full_name和函数表示法full_name(row)在 postgresql 中是等效的。

这意味着你要一张桌子

CREATE TABLE people (
  first_name text,
  last_name text
);
Run Code Online (Sandbox Code Playgroud)

和一个功能:

CREATE FUNCTION full_name(people) RETURNS text AS $$
  SELECT $1.first_name || ' ' || $1.last_name;
$$ LANGUAGE SQL;
Run Code Online (Sandbox Code Playgroud)

并这样称呼它:

select full_name from people
Run Code Online (Sandbox Code Playgroud)

那是你需要的吗?

为了加快速度,您可以创建一个表达式索引:

CREATE INDEX people_full_name_idx ON people
USING GIN (to_tsvector('english', full_name(people)));
Run Code Online (Sandbox Code Playgroud)

或者将所有内容存储在物化视图中。

示例取自此处:http : //bernardoamc.github.io/sql/2015/05/11/postgres-virtual-columns/

  • 这是正确答案。例如,请参阅 [Postgrest](https://postgrest.com/en/v4.3/api.html#computed-columns) 如何将此行为称为“计算列”。 (2认同)
  • 我只能使用`select people.full_name from people;`和`select full_name(people) from people`来处理上面的例子。没有前缀 `select full_name from people;` 的版本在 PostgreSQL 11 中出现错误:`SQL 错误 [42703]:错误:列“full_name”不存在` (2认同)

a_h*_*ame 6

不,目前(从 Postgres 9.6 开始)不支持此功能。

如果是不需要索引的简单计算,唯一的解决方法是使用触发器或视图。

  • 好吧,计算列就是这样:存储非规范化数据。如何生成计算列的值并不重要。我没有看到“真实”计算列和通过触发器生成的计算列之间的概念差异 (5认同)

Bas*_*que 6

是的: GENERATED ALWAYS AS … STORED

Postgres 12添加了生成列的功能,如SQL:2003标准中所述。

该值在INSERTor时生成UPDATE,然后像任何其他值一样与行一起存储。

生成的必须基于同一个表的基列,或基于不可变函数

语法很简单,一个子句CREATE TABLE

GENERATED ALWAYS AS ( generation_expr ) STORED 
Run Code Online (Sandbox Code Playgroud)

例子:

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

特征:

  • 可以编入索引。
  • SQL 标准的一部分。

注意事项:

  • 基于同一个表的列(非相关表)
  • 不允许分区(不能是分区键的一部分)
  • 数据总是写入行,占用存储空间
    • 未来的功能可能会为无需存储而即时计算的值提供 VIRTUAL
  • 单代深度(使用基列,而不是另一个生成的列)
  • 没有 GENERATED BY DEFAULT (您不能覆盖值)
  • 无法在 BEFORE 触发器中访问 gen-col(值尚未确定)
  • 函数必须是不可变的

看: