postgresql 如何检查数组是否为空

nvbavucw  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(5)|浏览(121)

我有一个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 ;

bihw5rsg

bihw5rsg1#

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。
在Postgres 9.4或更高版本中使用cardinality()See added answer by @bronzenose.
但是如果您要连接一个查询来使用EXECUTE运行,那么使用USING子句传递值会更明智。示例:

  • 多行子选择作为参数以使用执行
  • 如何使用EXECUTE FORMAT...在Postgres函数中使用

要像你的标题所说的那样显式地检查数组是否为空(但这不是你在这里需要的),只需将它与空数组进行比较:

id_clients = '{}'

仅此而已。你得到:
true..数组为空
null..数组为NULL
false..任何其他情况(数组有元素-即使只有null个元素)

fruv7luv

fruv7luv2#

如果出于某种原因,你不想提供数组的维数,cardinality将返回0表示一个空数组:
从文档:
cardinality(anyarray)返回数组中元素的总数,如果数组为空,则返回0

z2acfund

z2acfund3#

下面的示例接受array valuesNULLempty string作为查询参数。有些框架会在尝试传递NULL作为查询参数而发送空字符串时导致SQL错误。
查询使用jsonMap检查array-parameter是否为空:

SELECT CAST(ARRAY_TO_JSON(ARRAY[:myArrayParameter]) AS VARCHAR) IN ('[null]', '[""]')
64jmpszr

64jmpszr4#

检查数组是否为空的一种方法是使用array_ndims,它返回数组的维数,如果数组为空,则返回0。我使用的是PostgreSQL版本11。

$$
DECLARE

    IDS_PATROCINADOR_RED_0 INTEGER[] := ARRAY []::INTEGER[];
    IDS                        INTEGER;
BEGIN

    IF array_ndims(IDS_PATROCINADOR_RED_0) > 0 THEN
        IDS = array_length(ARRAY []::INTEGER, 1);
    ELSE
        IDS = 0 ;
    end if;
    RAISE NOTICE '%', IDS;
END

$$;
输出:

[2020-04-22 11:06:22] [00000] 0

[2020-04-22 11:06:22]完成时间143 ms

epfja78i

epfja78i5#

我在spring Boot 项目中遇到了这个问题。
我有一个数组列表参数,它可以是null或空的,如果它是空的,你应该忽略它。
这解决了一切。在repository检查list是否为空,并传递null表示它为空,否则会出现错误:

private static final String IDs = "Ids";
private static final String HAS_IDs = "hasIds";

...
parameters.addValue(IDs, CollectionUtils.isEmpty(params.getIds()) ? null : params.getIds());

创建一个布尔参数,说明list是否为空:

parameters.addValue(HAS_IDs, !CollectionUtils.isEmpty(params.getIds()));

在SQL中使用:

select * from table_name where
:hasIds = false or id in (:Ids)

相关问题