【发布时间】:2013-08-24 13:17:56
【问题描述】:
上下文
当函数返回TABLE 或SETOF 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) 将产生这些输出列:
2) select func(3) 将只产生一个 ROW 类型的输出列。
3) select (func(3)).* 会产生类似 #1 的结果:
当函数参数来自表或子查询时,语法#3 是唯一可能的,如:
select N, (func(N)).* from (select 2 as N union select 3 as N) s;
或在这个相关的answer 中。如果我们有LATERAL JOIN,我们可以使用它,但在 PostgreSQL 9.3 发布之前,它不受支持,而且之前的版本仍然会使用多年。
问题
现在语法 #3 的问题是函数被调用的次数与结果中的列数一样多。没有明显的原因,但它发生了。
通过在函数中添加RAISE NOTICE 'called for %', n,我们可以在 9.2 版本中看到它。通过上面的查询,它输出:
现在如果函数更改为返回 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 中是否有一种语法或构造可以通过只执行最少的所需函数调用来实现预期结果?
额外问题:为什么会发生多次评估?
【问题讨论】:
标签: postgresql user-defined-functions