我们写了一个函数get_timestamp()
,定义为:
CREATE OR REPLACE FUNCTION get_timestamp()
RETURNS integer AS
$$
SELECT (FLOOR(EXTRACT(EPOCH FROM clock_timestamp()) * 10) - 13885344000)::int;
$$
LANGUAGE SQL;
字符串
这是用于在数据库记录中的创建和修改字段中输入或编辑值。但是,我们发现当连续添加或更新记录时,它会返回相同的值。
在pgAdmin III中检查函数时,我们注意到在运行SQL构建函数时,LANGUAGE SQL语句后注入了关键字IMMUTABLE。documentation声明默认值为VOLATILE(如果这些都没有出现,VOLATILE是默认假设),所以我不确定为什么注入IMMUTABLE,但是,将其更改为STABLE解决了重复值的问题。
注意:* 正如在接受的答案中所述,IMMUTABLE永远不会被pgAdmin或Postgres添加到函数中,并且必须在开发过程中添加。
我猜发生的事情是,这个函数正在被评估,结果正在被缓存以进行优化,因为它被标记为IMMUTABLE,向Postgres引擎指示返回值不应该在给定相同(空)参数列表的情况下改变。然而,当不在触发器中使用时,当直接在JavaScript语句中使用时,该函数将返回一个不同的值五次,然后从那时起返回相同的值。这是由于一些优化算法,说什么“如果一个IMMUTABLE函数在一个会话中使用超过5次,缓存结果以备将来调用”
任何关于如何在Postgres函数中使用这些关键字的澄清都将受到欢迎。考虑到我们在触发器中使用此函数,STABLE对我们来说是正确的选择吗?或者还有其他需要考虑的事情,例如文档说:
(It不适用于希望查询由当前命令修改的行的AFTER触发器。)
但我不完全清楚为什么。
1条答案
按热度按时间4uqofj5v1#
关键字
IMMUTABLE
是never由pgAdmin或Postgres自动添加的。无论是谁创建或替换了该函数。给定函数的正确volatility是**
VOLATILE
(也是默认值),而不是STABLE
--否则使用clock_timestamp()
(VOLATILE
)与now()
或CURRENT_TIMESTAMP
(STABLE
)相比就没有意义了:它们在同一个事务中返回相同的时间戳。手册:clock_timestamp()
返回实际的当前时间,因此它的值即使在一个SQL命令中也会改变。不是
STABLE
。函数的manual warns的波动性
STABLE
.不适用于希望查询由当前命令修改的行的
AFTER
触发器。.因为它会在同一语句中期望相同的结果,并优化另一个查找。
你会问:
你知道为什么当设置为
IMMUTABLE
时,函数在坚持第五个值之前正确返回了五次吗?Postgres Wiki:
对于9.2,计划器将使用与发送的参数相关的特定计划(查询将在执行时计划),除非查询被执行多次**,并且计划器认为通用计划不会比特定计划花费太多。
粗体强调我的。对于没有输入参数的
IMMUTABLE
函数似乎没有意义。但是false标签被主体中的VOLATILE
函数覆盖(void * 函数内联 *):不同的查询计划仍然有意义。相关:一边
trunc()
比floor()
稍微快一点,在这里也是一样,因为正数是有保证的:字符串