引用时间戳时PostgreSQL错误生成表达式不是不可变的

v64noz0r  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(139)

当我尝试创建包含时间戳的生成tsvector列时,收到一个错误。错误是
错误:生成表达式不是不可变的 SQL状态:42P17
下面是我正在尝试使用的生成列。我试过删除格式,但似乎没有帮助。
CREATE TABLE lms.test_person ( first_name text, last_name text, date_of_birth timestamp without time zone, search tsvector GENERATED ALWAYS AS (to_tsvector('english', first_name || ' ' || last_name || ' ' || TO_CHAR(date_of_birth, 'YYYY-MM-DD') )) STORED );
我也试过
CREATE TABLE lms.test_person ( first_name text, last_name text, date_of_birth timestamp without time zone, search tsvector GENERATED ALWAYS AS (to_tsvector('english', first_name || ' ' || last_name || ' ' || date_of_birth::text )) STORED );
因为我读到非文本项的连接不是不可变的,但这似乎也不起作用。
如果我从to_tsvector中删除date_of_birth,一切都正常。我用的是15.1版

kgsdhlau

kgsdhlau1#

我们可以通过创建自己的不可变 Package 器函数并使用它来解决这个问题,

CREATE FUNCTION immutable_to_char(timestamp without time zone) RETURNS text AS
$$ select TO_CHAR($1, 'YYYY-MM-DD'); $$
LANGUAGE sql immutable;

然后执行查询,

CREATE TABLE lms.test_person ( 
    first_name text, 
    last_name text, 
    date_of_birth timestamp without time zone, 
    search tsvector GENERATED ALWAYS AS  (
        to_tsvector('english', 
                    first_name || ' ' || 
                    last_name  || ' ' || 
                    immutable_to_char(date_of_birth) 
                   )
    ) STORED 
);
y0u0uwnf

y0u0uwnf2#

我终于找到了一个可行的解决方案。这是一个将正确的不可变函数拼凑在一起以使其工作的问题。我使用date_part来提取我需要的部分并手动格式化它。注意:我使用了与我最初发布的格式不同的格式,但解决方案可以调整为使用上述格式。我还使用了使用\df+从psql提示符检查函数的不变性的建议

\df+ to_tsvector

这是我最后得出的结论。

CREATE TABLE lms.test_person (
    first_name text,
    last_name text,
    date_of_birth timestamp without time zone,
    search tsvector GENERATED ALWAYS AS 
    (to_tsvector('english', first_name || ' ' || last_name || ' ' || lpad(date_part('month', date_of_birth)::text, 2, '0') || lpad(date_part('day', date_of_birth)::text, 2, '0') || lpad(date_part('year', date_of_birth)::text, 4, '0') )) STORED
);

相关问题