返回 NULL 的空数组的 array_length()
Posted
技术标签:
【中文标题】返回 NULL 的空数组的 array_length()【英文标题】:array_length() of an empty array returning NULL 【发布时间】:2011-08-08 16:33:48 【问题描述】:我正在 PL/pgSQL 中开发一些存储过程,其中一些给我带来了一些问题。我正在开发的存储过程通过参数接收一个数组,我在 FOR LOOP 中使用该数组来获取其所有元素。为了定义 FOR LOOP 的上限,我使用了 array_length 函数。
FOR i IN 1..array_length(array,1) LOOP
--array[i] something in here
END LOOP;
当我给存储过程一个空数组时,就会出现问题。 sproc 不是不进入循环,而是简单地返回一个错误,说明 FOR LOOP 的上限为 NULL。不应该是0吗?
我在 FOR LOOP 上做错了吗?
在使用空数组时,有没有其他方法可以在 LOOP 中使用相同的边界而不返回 NULL?
注意:我知道我总是可以在 LOOP 之前使用条件,如下所示:
IF array_length(array,1) IS NOT NULL THEN
但问题是:这个存储过程应该在最短的时间内处理数千个调用。因此,我不希望在处理中增加不必要的开销。我只是在寻找是否有任何方法可以在 LOOP 中“循环”一个空数组。
【问题讨论】:
【参考方案1】:与往常一样,如果您希望 NULL 值具有不同的行为,请使用 coalesce
构造:
FOR i IN 1..coalesce(array_length(array, 1), 0) LOOP
RAISE NOTICE '%', array[i];
END LOOP;
关于返回值:array_length(x, N)
返回Nth维度的元素个数。由于空数组没有维度,因此它返回 NULL。你说得对,如果你只考虑简单的数组是违反直觉的,但对多维数组来说是有意义的。
编辑:就像 Erwin Brandstetter 在 cmets 中所写,使用 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;
【讨论】:
由于 Postgres 支持 arbitrary array subscripts,此表单仍然不是 100% 安全的。您必须使用array_lower()
和array_upper()
才能确定。
对于上限,不应该是 coalesce(array_upper(array, 1), 0) 吗?因为 1 .. 1 仍然会使其进入循环一次。【参考方案2】:
通过使用 FOREACH
循环遍历数组来完全避免这个问题,这是 Postgres 9.1 引入的:
FOREACH i IN ARRAY $1
LOOP
-- do something
END LOOP;
根据您想要在循环中执行的操作,您可能能够完全避免循环并使用带有unnest()
的普通SQL。基于集合的操作通常比 PostgreSQL 中的循环更快。
例子:
RETURN QUERY
SELECT elem || 'foo'
FROM unnest($1) AS t(elem);
【讨论】:
以上是关于返回 NULL 的空数组的 array_length()的主要内容,如果未能解决你的问题,请参考以下文章
Java中应该返回零长度数组或空集合,而不是返回null(转)
-[__NSArrayM objectAtIndex:]:索引 0 超出了带有 userInfo 的空数组的界限(null)
为啥使用 null 函数而不是 == [] 来检查 Haskell 中的空列表?
如何写sql语句去掉oracle返回结果中的空值(NULL)