我有一个 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;
$$;
所以如果我运行这样的查询:
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
;
最佳答案
array_length()
需要两个参数,第二个是数组的维度:
array_length(id_clients, 1) > 0
所以:
IF array_length(id_clients, 1) > 0 THEN
query := query || format(' AND id = ANY(%L))', id_clients);
END IF;
这不包括空数组和 NULL。
或者使用cardinality()
在 Postgres 9.4 或更高版本中。 See added answer by @bronzenose.
但是,如果您连接一个查询以使用 EXECUTE
运行,则使用 USING
子句传递值会更明智。示例:
- Multirow subselect as parameter to `execute using`
- How to use EXECUTE FORMAT ... USING in postgres function
顺便说一句,要显式检查数组是否为空(如您的标题所说 - 但不是您在这里需要的)只需将其与空数组进行比较:
id_clients = '{}'
就是这样。你得到:
TRUE
..数组为空
NULL
.. 数组为 NULL
FALSE
.. 任何其他情况(数组有元素 - 即使只有 NULL 元素)
关于sql - 如何检查 Postgres 中的数组是否为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25155666/