我有一个Postgres函数:
CREATE OR REPLACE FUNCTION get_stats(
_start_date timestamp with time zone,
_stop_date timestamp with time zone,
id_clients integer[],
OUT date timestamp with time zone,
OUT profit,
OUT cost
)
RETURNS SETOF record
LANGUAGE plpgsql
AS $$
DECLARE
query varchar := '';
BEGIN
... -- lot of code
IF id_clients IS NOT NULL THEN
query := query||' AND id = ANY ('||quote_nullable(id_clients)||')';
END IF;
... -- other code
END;
$$;
所以如果我运行类似这样的query:
SELECT * FROM get_stats('2014-07-01 00:00:00Etc/GMT-3'
, '2014-08-06 23:59:59Etc/GMT-3', '{}');
生成的查询具有以下条件:
"... AND id = ANY('{}')..."
但如果数组为空,则不应在查询中表示此条件。
如何检查客户端数组是否不为空?
我也尝试了两种变体:
IF ARRAY_UPPER(id_clients) IS NOT NULL THEN
query := query||' AND id = ANY ('||quote_nullable(id_clients)||')';
END IF;
并且:
IF ARRAY_LENGTH(id_clients) THEN
query := query||' AND id = ANY ('||quote_nullable(id_clients)||')';
END IF;
在这两种情况下,我得到了这个错误:ARRAY_UPPER(ARRAY_LENGTH) doesn't exists
;
5条答案
按热度按时间bihw5rsg1#
array_length()
需要 * 两个 * 参数,第二个是数组的维数:所以:
这排除了空数组 * 和 * NULL。
在Postgres 9.4或更高版本中使用
cardinality()
。See added answer by @bronzenose.但是如果您要连接一个查询来使用
EXECUTE
运行,那么使用USING
子句传递值会更明智。示例:使用
执行要像你的标题所说的那样显式地检查数组是否为空(但这不是你在这里需要的),只需将它与空数组进行比较:
仅此而已。你得到:
true
..数组为空null
..数组为NULLfalse
..任何其他情况(数组有元素-即使只有null
个元素)fruv7luv2#
如果出于某种原因,你不想提供数组的维数,
cardinality
将返回0表示一个空数组:从文档:
cardinality(anyarray)返回数组中元素的总数,如果数组为空,则返回0
z2acfund3#
下面的示例接受
array values
、NULL
或empty string
作为查询参数。有些框架会在尝试传递NULL
作为查询参数而发送空字符串时导致SQL错误。查询使用jsonMap检查array-parameter是否为空:
64jmpszr4#
检查数组是否为空的一种方法是使用array_ndims,它返回数组的维数,如果数组为空,则返回0。我使用的是PostgreSQL版本11。
$$;
输出:
[2020-04-22 11:06:22]完成时间143 ms
epfja78i5#
我在spring Boot 项目中遇到了这个问题。
我有一个数组列表参数,它可以是null或空的,如果它是空的,你应该忽略它。
这解决了一切。在repository检查list是否为空,并传递null表示它为空,否则会出现错误:
创建一个布尔参数,说明list是否为空:
在SQL中使用: