How to check if an array is empty in Postgres

SqlArraysPostgresqlStored ProceduresNull

Sql Problem Overview


I have a Postgres function:

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;
$$;

So if I run query something like this:

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

Generated query has this condition:

"... AND id = ANY('{}')..."

But if an array is empty this condition should not be represented in query.
How can I check if the array of clients is not empty?

I've also tried two variants:

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

And:

IF ARRAY_LENGTH(id_clients) THEN
    query := query||' AND id = ANY ('||quote_nullable(id_clients)||')';
END IF;

In both cases I got this error: ARRAY_UPPER(ARRAY_LENGTH) doesn't exists;

Sql Solutions


Solution 1 - Sql

array_length() requires two parameters, the second being the dimension of the array:

array_length(id_clients, 1) > 0

So:

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

This excludes both empty array and NULL.

Or use cardinality() in Postgres 9.4 or later. See added answer by @bronzenose.


But if you're concatenating a query to run with EXECUTE, it would be smarter to pass values with a USING clause. Examples:


BTW, to explicitly check whether an array is empty (like your title says - but that's not what you need here) just compare it to an empty array:

id_clients = '{}'

That's all. You get:

TRUE .. array is empty
NULL .. array is NULL
FALSE .. any other case (array has elements - even if just NULL elements)

Solution 2 - Sql

if for some reason you don't want to supply the dimension of the array, cardinality will return 0 for an empty array:

From the docs: > cardinality(anyarray) returns the total number of elements in the > array, or 0 if the array is empty

Solution 3 - Sql

Below example accepts array values, NULL or empty string as query parameter. Some frameworks result in an SQL error when you try to pass NULL as query parameter and you send an empty string instead.

The query checks if array-parameter is empty using json mapping:

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

Solution 4 - Sql

One way to check if the array is empty would be with array_ndims which returns the number of dimensions of the array, if the array is empty it will return 0. I'm working with version 11 postgresql.

$$
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

$$;

output:

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

[2020-04-22 11:06:22] completed in 143 ms

Solution 5 - Sql

I had this problem in spring boot project with postgresql.

I had an array list parameter which can be null or empty, and if it's empty you should ignore it.

This solved everything. In repository check if list is empty or not, and pass null is it's empty, otherwise you will have error:

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

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

Make a boolean paramener which says if list is empty or not:

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

In SQL use this:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjoni jonesView Question on Stackoverflow
Solution 1 - SqlErwin BrandstetterView Answer on Stackoverflow
Solution 2 - SqlbronzenoseView Answer on Stackoverflow
Solution 3 - SqlZonView Answer on Stackoverflow
Solution 4 - SqlzannierView Answer on Stackoverflow
Solution 5 - Sqleku-codeView Answer on Stackoverflow