错误:索引表达式中的函数必须在Postgres中标记为IMMUTABLE

fra*_*ncs 20 sql postgresql

我想创建一个Multicolumn表达式索引,但是当我创建索引时,会输出以下消息:

--detail message 
wapgrowth=> create index CONCURRENTLY idx_test on  tmp_table using btree (skyid, to_char(create_time, 'YYYY-MM-DD'), actiontype );
ERROR:  functions in index expression must be marked IMMUTABLE


--table ddl
wapgrowth=> \d tmp_table
               Table "wapgrowth.tmp_table"
   Column    |            Type             |   Modifiers   
-------------+-----------------------------+---------------
 id          | integer                     | not null
 actiontype  | character varying(20)       | 
 apptype     | character varying(20)       | 
 score       | integer                     | 
 create_time | timestamp without time zone | default now()
 skyid       | integer                     | 
Indexes:
Run Code Online (Sandbox Code Playgroud)

a_h*_*ame 21

根据黑客邮件列表中的这个帖子:

http://www.mail-archive.com/pgsql-hackers@postgresql.org/msg86725.html

这是to_char取决于LC_MESSAGES设置的预期行为

在你的情况下,这显然没有意义,因为你使用的格式永远不会依赖于语言环境,所以如果你确实需要在索引中使用文本表示,你可以创建自己的to_char()函数并将其标记为一成不变的:

CREATE OR REPLACE FUNCTION my_to_char(some_time timestamp) 
  RETURNS text
AS
$BODY$
    select to_char($1, 'yyyy-mm-dd');
$BODY$
LANGUAGE sql
IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)

如果必须将它用作索引中的文本(并且不能像Sam建议的那样使用强制转换),则需要创建自己的格式化函数,并将其标记为不可变.然后可以在索引中使用它.

但是要使Postgres 使用索引,您还需要my_to_char()在SQL语句中调用它.使用内置程序时无法识别它to_char()

但我确实认为Sam在索引中使用直接日期的建议可能更好


hol*_*vaj 13

这更详细地解释了:

https://www.postgresql.org/message-id/CAKFQuwbcMfesmNkm19mXFLXP14sP5BiPsR1GSkY1suKiM1rukg%40mail.gmail.com

基本上时区取决于服务器,因此如果有人更改它,结果可能会改变。但是如果你锁定时区:

date(timezone('UTC', create_time)

它会起作用。

  • 太棒了,包装我的日期/时间列 - `timezone('UTC', date_time_column)` - 就是我需要做的所有事情(即不需要声明不可变函数)。谢谢! (2认同)