我试图在选择查询中的多维数组列(int[][]
)上运行plpgsql函数。
功能如下:
CREATE OR REPLACE FUNCTION public.reduce_to_percentages(int[][])
RETURNS float[] AS
$function$
DECLARE
s int[];
a float[];
BEGIN
FOREACH s SLICE 1 IN ARRAY $1 LOOP
a := a || s[2]::float / s[1]::float;
END LOOP;
RETURN a;
END;
$function$
LANGUAGE plpgsql VOLATILE;
以下查询有效:
SELECT reduce_to_percentages(ARRAY[ARRAY[100, 20], ARRAY[300, 50]]);
以下查询也是如此:
SELECT reduce_to_percentages((SELECT counts FROM objects LIMIT 1));
但是以下查询为函数提供了null
值,并在尝试FOREACH
$1
时导致异常:
SELECT reduce_to_percentages(counts) FROM objects;
答案 0 :(得分:2)
在函数体中只检查参数是否为空。如果要为null参数返回一个空数组,则在declare部分为变量a
添加一个初始值(否则该函数将返回null)。
CREATE OR REPLACE FUNCTION public.reduce_to_percentages(int[][])
RETURNS float[] AS
$function$
DECLARE
s int[];
a float[] = '{}'; -- initial value
BEGIN
IF $1 IS NOT NULL THEN
FOREACH s SLICE 1 IN ARRAY $1 LOOP
a := a || s[2]::float / s[1]::float;
END LOOP;
END IF;
RETURN a;
END;
$function$
LANGUAGE plpgsql VOLATILE;
我做了一个简单的测试。这是一个适度的设置:
create table test (val int[]);
insert into test
select (array[array[ri(100), ri(100)], array[ri(100), ri(100)]])
from generate_series(1, 1000000);
ri(100)
是我的函数,返回1-100之间的随机整数。
因此,该表包含一百万行,其中一列包含两个整数的两个数组。
我尝试了尽可能简单的测试和典型的。
以下查询已使用Erwin的函数执行了10次,使用我的变体执行了10次:
select sum(v[1]), sum(v[2])
from (
select reduce_to_percentages(val) v
from test
) s;
十次测试的平均执行时间:
也许我的功能是它的鼻子上有口红的猪,但速度很快。
答案 1 :(得分:2)
您可以通过检查NULL
值like @klin provided来修复错误。
但那是在猪上涂上口红。重写函数以使用基于集合的解决方案替换过程循环。通常更快(特别是在外部查询的上下文中使用时),更简单且自动为空安全:
CREATE OR REPLACE FUNCTION public.reduce_to_percentages(int[])
RETURNS float[] AS
$func$
SELECT ARRAY (SELECT $1[d][2]::float / $1[d][1]
FROM generate_subscripts($1,1) d)
$func$ LANGUAGE sql IMMUTABLE;
相关:
注意:
将红利投射到float
就足够了。 float / integer
会自动返回float
。
没有数据类型int[][]
。只需int[]
。 Postgres允许使用符号,但忽略数组类型的其他数组维度,因为数据类型本身对于所有维度都是相同的。详细说明:
创建函数IMMUTABLE
(因为 )以获得更好的性能并允许索引。相关:
或者 ,您可以将您的函数声明为STRICT
(同义词:RETURNS NULL ON NULL INPUT
)。次要差异:它为NULL输入返回NULL
,而不是像上面那样返回空数组('{}'
)。
CREATE OR REPLACE FUNCTION public.reduce_to_percentages(int[][])
RETURNS float[] AS
$function$
...
$function$ LANGUAGE plpgsql IMMUTABLE STRICT;
RETURNS NULL ON NULL INPUT
或STRICT
表示该功能 每当任何参数为null时,它总是返回null。如果这 指定参数,有时不执行该功能 null参数;而是自动假设空结果。
但由于多种原因,上面的简单SQL函数更可取。