我添加一些列到一个表,并希望生成一个列,将它们组合在一起,我将使用一个唯一的索引。当我尝试添加列时,我得到错误ERROR: generation expression is not immutable
。
我遵循了this question的解决方案,特别是使用CASE
和||
进行字符串连接,它们应该是immutable
。
ALTER TABLE tag
ADD COLUMN prefix VARCHAR(4) NOT NULL,
ADD COLUMN middle BIGINT NOT NULL,
ADD COLUMN postfix VARCHAR(4), -- nullable
-- VARCHAR size is 4 prefix + 19 middle + 4 postfix + 2 delimiter
ADD COLUMN tag_id VARCHAR(29) NOT NULL GENERATED ALWAYS AS
(CASE WHEN postfix IS NULL THEN prefix || '-' || middle
ELSE prefix || '-' || middle || '-' || postfix
END
) STORED;
CREATE UNIQUE INDEX unq_tag_tag_id ON tag(tag_id);
在postgres mailing list中,其中一位贡献者澄清了:
整数到文本强制,[...]不一定是不可变的
但是,他没有共享一个不可变的整数到文本的函数。有谁知道是否有一个?
2条答案
按热度按时间rxztt3cl1#
Marmite Bomber的回答显示了解决方案;让我补充一点说明。
text
有两个串联运算符:第一个操作符将
text
与text
连接起来,第二个操作符将text
与其他任何操作符连接起来。让我们看看这两个函数的波动性:
因此,如果您将
text
和bigint
连接起来,该操作不是IMMUTABLE
,但首先将bigint
转换为text
会产生IMMUTABLE
操作。并不是因为与整数连接,这个运算符就不是不可变的。但是
anynonarray
可以是任何数据类型,如timestamp with time zone
,其字符串表示取决于timezone
的当前设置。tyg4sfes2#
14.1中的测试表明,原因是串联中
bigint
列到text
的隐式转换(即使没有case
)显式转换为
text
不会产生错误-middle::text