sql - 如何检查 Postgres 中的数组是否为空

标签 sql arrays postgresql stored-procedures null

我有一个 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 子句传递值会更明智。示例:


顺便说一句,要显式检查数组是否为空(如您的标题所说 - 但不是您在这里需要的)只需将其与空数组进行比较:

id_clients = '{}'

就是这样。你得到:

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

关于sql - 如何检查 Postgres 中的数组是否为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25155666/

相关文章:

python - 在 Django 数据库中插入外键

c# - 将 View 和表映射到 EF 中的同一模型?

java - 将 2D 对象数组 JSON 反序列化为 Java

python - 如何将字符串列表转换为数字 numpy 数组?

java - 使用自定义适配器将 XML 中的数据解析为列表

python - Python 中 PostGIS 的 ST_DWithin 的替代方案

sql - PostgreSQL 更新不返回零计数

MYSQL,复制记录但更改列的值

python - pyodbc for 循环和 commit()

sql - 为什么在SQL查询中添加括号会导致结果更改?