【问题标题】:How to spec a GENERATED NUMRANGE?如何指定生成的数字范围?
【发布时间】:2021-12-10 13:32:24
【问题描述】:

下面的 GENERATED 子句都无法在 psql 中编译,出现错误 42601

什么是正确的语法? (或者不支持 GENERATED NUMRANGE 吗?)

CREATE TABLE lh  (
   l   NUMERIC,
   h   NUMERIC,

 --lhr NUMRANGE GENERATED ALWAYS AS  numrange(l,h)                    STORED
 --lhr NUMRANGE GENERATED ALWAYS AS  (l,h)::NUMRANGE                  STORED
 --lhr NUMRANGE GENERATED ALWAYS AS '(l,h)'::NUMRANGE                 STORED
 --lhr NUMRANGE GENERATED ALWAYS AS  (l::NUMERIC,h:NUMERIC)           STORED
   lhr NUMRANGE GENERATED ALWAYS AS  (l::NUMERIC,h:NUMERIC)::NUMRANGE STORED
);

【问题讨论】:

  • 意图是在 DDL 中定位一次写入逻辑
  • 问题是定义numrange 不会强制执行一次写入逻辑。您不能更新生成的列是正确的,但是更新它所基于的列会导致 Postgres 重新生成它。见demo。强制只写一次需要一个触发器。
  • 是的,谢谢,明白这一点,但在驱动应用程序的业务规则中,h & l 永远不会改变

标签: postgresql ddl


【解决方案1】:

你可以:

CREATE TABLE lh  (
   l   NUMERIC,
   h   NUMERIC,
   lhr NUMRANGE GENERATED ALWAYS AS  (numrange(l,h)) STORED
);

您需要在() 中包含表达式。

不知道您为什么要这样做,因为它只是复制现有数据,这些数据可以像numrange(l,h) AS lhr 一样轻松包含在查询中。

【讨论】:

  • 谢谢!是的,多余的,但 'hlr' 是数据库应用程序的基础,因此更喜欢重用 3 字符标识符而不是在所有将使用它的块中运行/键入“numrange(l,h) AS lhr”。
  • ('lhr',不是 'hlr')
【解决方案2】:

如果您只是将范围用作SELECT 方便,请使用VIEW

CREATE VIEW lh_range AS
SELECT l, h, numrange(l, h) AS lhr
FROM lh

live demo

【讨论】:

  • 是的,有道理,谢谢。有什么理由不将视图变为 MATERIALIZED 吗? -- 会有大量的关系建立在上面。
  • 是的,你可以CREATE MATERIALIZED VIEW,它会执行得更快,但是当新行添加到基表时它不会自动刷新。但是,我不希望性能受到太大影响。基表的行大小节省的空间可能足以补偿动态生成的数字范围。我会测试所有方法(额外的列、视图、物化视图)并比较性能。
猜你喜欢
  • 1970-01-01
  • 2023-03-06
  • 2020-03-01
  • 2015-07-21
  • 1970-01-01
  • 2011-05-15
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多