返回NULL的空数组的array_length()

时间:2011-08-08 16:33:49

标签: arrays postgresql plpgsql

我正在PL / pgSQL中开发一些存储过程,其中一些正在给我一些问题。我正在开发的sprocs通过参数接收一个数组,我在FOR LOOP中使用它来获取它的所有元素。要定义FOR LOOP的上限,我使用array_length函数。

FOR i IN 1..array_length(array,1) LOOP

   --array[i] something in here

END LOOP;

当我向sprocs提供一个空数组时会出现问题。 sproc只是返回一个错误,而不是不进入循环,说明FOR LOOP的上限是NULL。不应该 0 吗?

我对FOR LOOP做错了吗?

有没有其他方法可以在LOOP中使用相同的边界而不使用空数组时返回NULL?

注意:我知道我总是可以在LOOP之前使用条件,如下所示:

IF array_length(array,1) IS NOT NULL THEN

但问题是:这个sproc应该在最短的时间内处理数千个调用。因此,我并不期待为处理增加不必要的开销。我只是在寻找是否有办法在循环中“循环”一个空数组。

2 个答案:

答案 0 :(得分:14)

与往常一样,如果您希望对NULL值使用不同的行为,请使用coalesce构造:

FOR i IN 1..coalesce(array_length(array, 1), 0) LOOP
    RAISE NOTICE '%', array[i];
END LOOP;

至于返回值:array_length(x, N)返回第N 维度中的元素数量。由于空数组没有维度,因此返回NULL。你是对的,如果你只考虑简单的数组,它是违反直觉的,但对多维数组有意义。

编辑像Erwin Brandstetter在评论中写道,使用array_lower / upper循环数组索引更为正确。这些将适用于非基于1的阵列。这些也需要维度参数并需要合并:

FOR i IN coalesce(array_lower(array, 1), 1)..coalesce(array_upper(array, 1), 1) LOOP
    RAISE NOTICE '%', array[i];
END LOOP;

答案 1 :(得分:4)

通过使用Postgres 9.1 引入的FOREACH循环遍历数组来完全避免此问题:

FOREACH i IN ARRAY $1
LOOP
   -- do something
END LOOP;

根据您在循环中要执行的操作,您可以完全避免循环,并使用纯unnest()代替SQL。基于集合的操作通常比在PostgreSQL中循环更快。

示例:

RETURN QUERY
SELECT elem || 'foo'
FROM unnest($1) AS t(elem);