语境
当函数返回 aTABLE
或 aSETOF composite-type
时,例如这个示例函数:
CREATE FUNCTION func(n int) returns table(i int, j bigint) as $$
BEGIN
RETURN QUERY select 1,n::bigint
union all select 2,n*n::bigint
union all select 3,n*n*n::bigint;
END
$$ language plpgsql;
可以通过多种方法访问结果:
1)select * from func(3)
将产生这些输出列:
我 | j ---+--- 1 | 3 2 | 9 3 | 27
2)select func(3)
将只产生一个 ROW 类型的输出列。
功能 -------- (1,3) (2,9) (3,27)
3)select (func(3)).*
将产生像#1:
我 | j ---+--- 1 | 3 2 | 9 3 | 27
当函数参数来自表或子查询时,语法#3 是唯一可能的,如下所示:
select N, (func(N)).* from (select 2 as N union select 3 as N) s;
或者在这个相关的答案中。如果我们有LATERAL JOIN
我们可以使用它,但是在 PostgreSQL 9.3 出来之前,它不受支持,而且以前的版本仍然可以使用多年。
问题
现在语法 #3 的问题是函数被调用的次数与结果中的列数一样多。没有明显的原因,但它发生了。我们可以在 9.2 版本中通过RAISE NOTICE 'called for %', n
在函数中添加 a 来看到它。通过上面的查询,它输出:
注意:要求 2 注意:要求 2 注意:要求 3 注意:要求 3
现在,如果函数更改为返回 4 列,如下所示:
CREATE FUNCTION func(n int) returns table(i int, j bigint,k int, l int) as $$
BEGIN
raise notice 'called for %', n;
RETURN QUERY select 1,n::bigint,1,1
union all select 2,n*n::bigint,1,1
union all select 3,n*n*n::bigint,1,1;
END
$$ language plpgsql stable;
然后相同的查询输出:
注意:要求 2 注意:要求 2 注意:要求 2 注意:要求 2 注意:要求 3 注意:要求 3 注意:要求 3 注意:要求 3
需要 2 个函数调用,实际调用了 8 个。该比率是输出列的数量。
除了输出列布局之外,使用产生相同结果的语法 #2,这些多次调用不会发生:
select N,func(N) from (select 2 as N union select 3 as N) s;
给出:
注意:要求 2 注意:要求 3
接下来是 6 个结果行:
n | 功能 ---+------------ 2 | (1,2,1,1) 2 | (2,4,1,1) 2 | (3,8,1,1) 3 | (1,3,1,1) 3 | (2,9,1,1) 3 | (3,27,1,1)
问题
是否有 9.2 的语法或构造可以通过仅执行最少的所需函数调用来实现预期结果?
额外的问题:为什么会发生多次评估?