我有timestampz列,名为created,我希望使用Postgres 12+generated columns从它创建为月、日和年生成的列.

由于timestampz中有一个时区,因此像date_part(create, ..)EXTRACT (month from created)这样的表达式会失败,并显示错误:

ERROR: generation expression is not immutable

我try 将时间戳转换为时间戳并修复时区,但两者仍然被认为是可变的生成表达式:

  1. GENERATED ALWAYS AS (date_part('month', created::timestamp))
  2. GENERATED ALWAYS AS (date_part('month', created::timestamp AT TIME ZONE 'UTC'))

然而,正如Erwin Brandstetter在他对this answer的 comments 中所指出的那样,这是可行的:

ALTER TABLE tbl
ADD COLUMN created_year numeric GENERATED ALWAYS AS 
    (date_part('month', created AT TIME ZONE 'UTC')) STORED;

当然,EXTRACT(month from created AT TIME ZONE 'UTC'))也行得通.

That leads me to the conclusion that if I want N timezones, I need N generated columns.
Why does this work and not #2 above? Does it have to do with the servers' configuration params when doing ::timestamp datatype conversion?

推荐答案

为什么这行得通,而不是上面的第二条呢?

#1和#2都不起作用,因为从timestamptztimestamp的强制转换不是immutable.这取决于当前的timezone设置.由于显而易见的原因,生成的列只接受不可变的表达式.需要注意的是:timezone不是"服务器设置",而是每个单独会话的设置.默认设置通常是postgresql.conf,但客户端可以(并且经常会)根据需要设置它.

另一方面,date_part('month', created AT TIME ZONE 'UTC是一成不变的.派生UTC时间(或任何给定时区偏移量的本地时间)始终会产生相同的结果,并且在此表达式中,时区是给定的常量.

不幸的是,数据类型timestamp with time zone的名称有点误导.给定的时区根本不存储.它只是作为输入修饰符来计算相应的UTC时间,该时间存储在内部.(作为输出修饰符,调整为请求客户端的timezone.)请参阅:

基本信息:

Postgresql相关问答推荐

将具有自定义类型的表从一种模式复制到另一种模式

如何在 MockDataProvider 中创建自定义 JOOQ 记录?

PostgreSQL - 继承表的常见自动增量

在 KnexJS 中插入

PostgreSQL:在timestamp::DATE 上创建索引

Java - 日期保存为前一天

AWS RDS 公开访问

包含受先前 DELETE 影响的行数的变量?

在执行 postgresql 函数时提交事务

在 postgres 中删除所有共享相同前缀的表

PostgreSQL如何连接间隔值'2天'

Postgres 删除表语法错误

在 PostgreSQL 中显示正在运行的查询的全文

安装时 postgres 的默认用户

获取 psycopg2 count(*) 结果数

Hibernate 启动很慢

如何将 PostgreSQL 查询输出导出到 csv 文件

使用 Postgresql 在过滤器中制作 Sqlalchemy 使用日期

判断 PostgreSQL 中的角色是否设置了密码

重命名 Amazon RDS 主用户名