为什么无法转换为 PostgreSQL 索引中的时间戳?

bas*_*ser 5 postgresql index timestamp cast postgresql-12

我正在处理从外部源收到的 JSON 文档。在本文档中,有一个timestamp属性对应于timestampPostgreSQL 数据类型的文本格式。换句话说,它可以被转换为timestamp类型:(data->>'timestamp')::timestamp

我想timestamp在索引中使用该属性。我尝试了以下方法:

create table t
(
    data    jsonb
);

create index on t(((data->>'timestamp')::timestamp));
Run Code Online (Sandbox Code Playgroud)

我正进入(状态:

ERROR:  functions in index expression must be marked IMMUTABLE
Run Code Online (Sandbox Code Playgroud)

为什么是这样?我知道转换为 atimestamptz并不是不可变的,因为本地化配置设置不是静态的,但我无法将该逻辑应用于转换为timestamp.

还有办法将我的timestamp财产放入索引吗?

我正在使用几天前发布的 PostgreSQL 12。

Lau*_*lbe 5

text从到 的转换timestamp without time zone是通过调用类型输入函数来处理的timestamp_in,该函数是STABLE

原因是它timestamp_in也支持一些其他格式:

SELECT 'now'::timestamp;

         timestamp          
----------------------------
 2019-10-09 09:53:32.026673
(1 row)
Run Code Online (Sandbox Code Playgroud)

如果您知道您的输入始终是 ISO 时间戳并且这种情况不会发生,请定义您自己的转换函数:

CREATE FUNCTION text2ts(text) RETURNS timestamp without time zone
   LANGUAGE sql IMMUTABLE AS
$$SELECT CASE WHEN $1 ~ '^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(\.\d+)?$'
            THEN CAST($1 AS timestamp without time zone)
       END$$;
Run Code Online (Sandbox Code Playgroud)

您可以在查询和索引中使用它。

如果您不偏执并且确信自己的数据质量,则可以省略该测试。这会提高性能,但如果有人now在数据中偷偷溜进了类似的东西,你就会面临索引损坏的风险。