PostgreSQL 8.2.3 中文文档
后退快退章33. 扩展 SQL快进前进

33.6. 函数易失性范畴

每个函数都有一个易失性级别(VOLATILE, STABLE, IMMUTABLE)。如果 CREATE FUNCTION 命令没有明确声明范畴的话,VOLATILE 就是缺省。易失性范畴是给优化器的一个关于函数行为的承诺:

为了最佳的优化结果,应该尽可能使用最严格的易失性范畴标记你的函数。

任何有副作用的函数都必须标记为 VOLATILE ,这样对它的调用就不会被优化。即使一个函数没有副作用,但它的数值可能在一个查询里改变,那么也必须标记为 VOLATILE ;例如 random(), currval(), timeofday() 函数。

在那些简单的规划后马上执行的交互查询上,STABLEIMMUTABLE 没有什么区别:函数是在规划开始时执行还是在查询开始时执行的差别并不大。但是如果规划被保存并且后来被重用,那差别可就大了。如果把一个函数标记为 IMMUTABLE 而它实际上又不是,那么就会导致在随后使用其规划的时候用上一个不完整的数值。如果在使用预先准备好语句或者使用一种缓冲规划的函数语言(比如 PL/pgSQL),那么后果可能很严重。

因为 MVCC 的快照行为(参阅章12),一个只包含 SELECT 命令的函数可以安全地标记为 STABLE ,即使它所选择的表可能会被其它并发查询修改也一样。PostgreSQL 将会在执行 STABLE 函数时为调用它的查询建立快照,因此它在该查询的生存期内都会看到一致的数据库视图。还要指出的是,current_timestamp 函数族都是稳定的,因为它们的数值在一个事务里是不改变的。

同样的快照行为也用于 IMMUTABLE 函数里面的 SELECT 命令。通常,在一个 IMMUTABLE 函数里选择一个数据库的表是不明智的,因为如果表的内容改变,那么这种不变性就将改变。不过,PostgreSQL 并不禁止你这样做。

一个常见的错误是把一个函数标记为 IMMUTABLE ,而实际上这个函数的结果依赖某个配置参数。比如,一个操作时间戳的函数可能有依赖于 timezone 设置的结果。为了安全考虑,这样的函数应该标记为 STABLE

【注意】在 PostgreSQL 8.0 之前,要求 STABLEIMMUTABLE 函数不能修改数据库这个约束并未由系统强制。版本 8.0 通过要求这类函数不能包含 SELECT 之外的 SQL 命令来强制这个约束。不过,这么做并不是完全防弹的升级,因为这样的函数仍然可以调用那些可能修改数据库的 VOLATILE 函数。如果你这么做的话将会发现 STABLEIMMUTABLE 并不会觉察到被它调用的函数对数据库所做的修改。


后退首页前进
函数重载上一级过程语言函数