如何在Postgres中检查数组是否为空

jon*_*nes 31 sql arrays postgresql null stored-procedures

我有一个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;
$$;
Run Code Online (Sandbox Code Playgroud)

所以如果我运行这样的查询:

SELECT * FROM get_stats('2014-07-01 00:00:00Etc/GMT-3'
                      , '2014-08-06 23:59:59Etc/GMT-3', '{}');
Run Code Online (Sandbox Code Playgroud)

生成的查询具有以下条件:

"... AND id = ANY('{}')..."
Run Code Online (Sandbox Code Playgroud)

但是如果数组为空,则不应在查询中表示此条件.
如何检查客户端数组是否为空?

我也尝试了两种变体:

IF ARRAY_UPPER(id_clients) IS NOT NULL THEN
    query := query||' AND id = ANY ('||quote_nullable(id_clients)||')';
END IF;
Run Code Online (Sandbox Code Playgroud)

和:

IF ARRAY_LENGTH(id_clients) THEN
    query := query||' AND id = ANY ('||quote_nullable(id_clients)||')';
END IF;
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,我得到这个错误:ARRAY_UPPER(ARRAY_LENGTH) doesn't exists;

Erw*_*ter 57

array_length()需要两个参数,第二个是数组的维度:

array_length(id_clients, 1) > 0
Run Code Online (Sandbox Code Playgroud)

所以:

IF array_length(id_clients, 1) > 0 THEN
    query := query || format(' AND id = ANY(%L))', id_clients);
END IF;
Run Code Online (Sandbox Code Playgroud)

这排除了空数组 NULL.


但是如果你要连接一个运行的查询EXECUTE,那么用一个USING子句传递值会更聪明.例子:


顺便说一句,要明确检查一个数组是否为空(就像你的标题所说 - 但这不是你需要的),只需将它与一个空数组进行比较:

id_clients = '{}'
Run Code Online (Sandbox Code Playgroud)

就这样.你得到:

TRUE..数组为空
NULL..数组为NULL
FALSE..任何其他情况(数组有元素 - 即使只是NULL元素)


小智 17

如果由于某种原因你不想提供数组的维度,cardinality则为空数组返回0:

来自文档:

cardinality(anyarray)返回数组中元素的总数,如果数组为空,则返回0