我在表中有一个jsonb列event
。我正在尝试创建索引
CREATE INDEX ON table(((events->'START'->> 'date')::timestamp AT TIME ZONE 'PST'));
但是它抛出错误functions in index expression must be marked IMMUTABLE
在传递了时区之后,它应该保持不变,但是我不确定为什么它仍然会引发错误。
答案 0 :(得分:1)
强制转换为timestamp
是您的问题。它不是IMMUTABLE
,因为使用的函数接受now
之类的参数。
如果确定您的数据仅包含常规时间戳记且不包含此类值,则可以定义自己的IMMUTABLE LANGUAGE sql
函数来包装类型转换。
您可以在查询中使用此类功能并将其编入索引。如果存在确实不是强制转换的值,则索引将被破坏。
答案 1 :(得分:0)
我正在使用自己的方法来扩大Laurenz Albe的回答,以便能够发布代码。
假设您有一个表mytable
和JSONB字段thedata
,其中包含类似{ "datetime": "2020-03-21T33:44:55.193843281Z ", ... }
的数据:
-- Create immutable UTC parsing function, see:
-- * https://stackoverflow.com/questions/58877503/cant-create-an-index-on-a-jsonb-field-with-date
-- * https://stackoverflow.com/questions/5973030/error-functions-in-index-expression-must-be-marked-immutable-in-postgres
-- It parses dates of format:
-- YYYY-MM-DDTHH:MM:SSZ
-- (with a 'T' between date and time, and a 'Z' at the end) for example:
-- 2020-03-21T33:44:55Z
-- 2020-03-21T33:44:55.193843281Z
CREATE OR REPLACE FUNCTION utc_to_timestamp(some_time text)
RETURNS timestamp with time zone
AS
$BODY$
select to_timestamp($1, 'YYYY-MM-DD"T"HH24:MI:SS"Z"');
$BODY$
LANGUAGE sql
IMMUTABLE;
-- Define the index:
CREATE INDEX mytable_expr_datetime on mytable (utc_to_timestamp(the_data ->> 'datetime'));
因此,对于问题中的表/字段名称,必须将the_data ->> 'datetime'
替换为events->'START'->> 'date'
,将mytable
替换为events
。