【问题标题】:Does PostgreSQL only support STORED generated columns? [duplicate]PostgreSQL 是否只支持 STORED 生成的列? [复制]
【发布时间】:2020-09-08 16:21:27
【问题描述】:

前言

我已经给出了一些 PHP 的例子来说明我的开发环境。问题不在于 PHP,而纯粹是关于 PostgreSQL。


PostgreSQL documentation about generated column 声明:

生成的列有两种:存储列和虚拟列。存储生成的列在写入(插入或更新)时计算,并像普通列一样占用存储空间。虚拟生成的列不占用存储空间,在读取时计算。

但是,它仅在该页面的示例中显示了 存储列 的示例,而不是虚拟的。它还说:

必须指定关键字 STORED 以选择生成列的存储类型。有关详细信息,请参阅创建表。

...它链接到CREATE TABLE page。在该页面中,文档清楚地指出模式是GENERATED ALWAYS AS (expression) STORED

生成总是作为 (generation_expr) 存储

此子句将列创建为生成列。该列无法写入,读取时指定的结果 表达式将被返回。

需要关键字 STORED 来表示该列将在写入时计算并将存储在磁盘上。

生成表达式可以引用表中的其他列,但不能引用其他生成的列。使用的任何函数和运算符都必须是不可变的。不允许引用其他表。

我实际上尝试在 Laravel (PHP) 中实现一个虚拟字段,这是我迄今为止在迁移中想出的:

DB::statement('ALTER TABLE entries ADD COLUMN do_hint BOOLEAN GENERATED ALWAYS AS (hint_hash OR hint_tags OR hint_due_date OR hint_created_at OR hint_updated_at) VIRTUAL');

正如您在此语句中看到的,entries 表中有hint_hashhint_tags 和其他几个布尔列(以hint_* 全局模式命名)。我想即时计算do_hint,以便:

  • 我实际上可以从数据库中查询它。当然,我也可以在 PHP 上生成它,但我想查询,这就是我想使用虚拟列的重点。
  • 我想依赖 PostgreSQL 而不是 PHP 的性能。

考虑到 stored 列只生成一次(插入行时),这不是我想要的行为。我想要一个虚拟专栏,以便我可以随时阅读。

我的代码中出现语句错误。

  SQLSTATE[42601]: Syntax error: 7 ERROR:  syntax error at or near "VIRTUAL"
LINE 1: ...hint_due_date OR hint_created_at OR hint_updated_at) VIRTUAL
                                                                ^ (SQL: ALTER TABLE entries ADD COLUMN do_hint BOOLEAN GENERATED ALWAYS AS (hint_hash OR hint_tags OR hint_due_date OR hint_created_at OR hint_updated_at) VIRTUAL)

它指向VIRTUAL 部分是问题所在。所以我想“也许,virtual 生成的列是默认行为。”所以我删除它并再次尝试,但它再次失败,抱怨必须定义生成列的类型:

  SQLSTATE[42601]: Syntax error: 7 ERROR:  syntax error at end of input
LINE 1: ...tags OR hint_due_date OR hint_created_at OR hint_updated_at)
                                                                       ^ (SQL: ALTER TABLE entries ADD COLUMN do_hint BOOLEAN GENERATED ALWAYS AS (hint_hash OR hint_tags OR hint_due_date OR hint_created_at OR hint_updated_at))

所以,我的问题就在标题中:PostgreSQL 在这个时间点上是否只支持 存储的虚拟列?目前没有办法获取虚拟列吗?

我的意思是,当文档说“有两种生成的列:存储列和虚拟列。”时,我感到很困惑。是 (i) 只是尝试在此处引入 virtual存储生成列 的概念,还是 (ii) 宣传它在 PostgreSQL 12 上具有的新功能?我的意思是,如果无法创建虚拟生成的列,他们可以添加一条警告说“此时无法使用虚拟生成的列。我们只支持存储的列。”但是文档中的任何地方都没有这样的警告。我很困惑。

提前致谢。


环境

  • PHP 7.4.5
  • Laravel 7
  • PostgreSQL 12.2

【问题讨论】:

    标签: sql postgresql create-table generated-columns


    【解决方案1】:

    是的,目前 PostgreSQL 只支持存储生成的列。

    您可以使用视图来获取虚拟生成列的功能。

    【讨论】:

      【解决方案2】:

      不支持虚拟生成列的documentation clearly states

      PostgreSQL 目前只实现存储生成的列。

      这仅出现在您引用的文档部分之后的一句话。

      【讨论】:

      • 好吧,没看到那个,浪费了我生命中的 30 分钟和你的 2 分钟。不管怎样,Stackoverflow 会让我在 6 分钟内接受这个答案。谢谢。
      猜你喜欢
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-25
      • 1970-01-01
      • 1970-01-01
      • 2015-09-20
      • 1970-01-01
      相关资源
      最近更新 更多