Skip to content
Advertisement

Check if NULL exists in Postgres array

Similar to this question, how can I find if a NULL value exists in an array?

Here are some attempts.

Only a trick with array_to_string shows the expected value. Is there a better way to test this?

Advertisement

Answer

Postgres 9.5 or later

Or use array_position(). Basically:

See demo below.

Postgres 9.3 or later

You can test with the built-in functions array_remove() or array_replace().

Postgres 9.1 or any version

If you know a single element that can never exist in your arrays, you can use this fast expression. Say, you have an array of positive numbers, and -1 can never be in it:

Related answer with detailed explanation:

If you cannot be absolutely sure, you could fall back to one of the expensive but safe methods with unnest(). Like:

or:

But you can have fast and safe with a CASE expression. Use an unlikely number and fall back to the safe method if it should exist. You may want to treat the case arr IS NULL separately. See demo below.

Demo

Result:

 num |  arr        | expect | t_1    | t_2  | t_3 | t_91 | t_93a | t_93b | t_94 | t_95a | t_95b | t_95c
-----+-------------+--------+--------+------+-----+------+-------+-------+------+-------+-------+-------
   1 | {1,2,NULL}  | t      | t      | t    | t   | t    | t     | t     | t    | t     | t     | t
   2 | {-1,NULL,2} | t      | f --!! | t    | t   | t    | t     | t     | t    | t     | t     | t
   3 | {NULL}      | t      | t      | t    | t   | t    | t     | t     | t    | t     | t     | t
   4 | {1,2,3}     | f      | f      | f    | f   | f    | f     | f     | f    | f     | f     | f
   5 | {-1,2,3}    | f      | f      | f    | f   | f    | f     | f     | f    | f     | f     | f
   6 | NULL        | NULL   | t --!! | NULL | f   | NULL | NULL  | NULL  | NULL | f     | f     | NULL

Note that array_remove() and array_position() are not allowed for multi-dimensional arrays. All expressions to the right of t_93a only work for 1-dimenstioal arrays.

db<>fiddle here – Postgres 13, with more tests
Old sqlfiddle

Benchmark setup

The added times are from a benchmark test with 200k rows in Postgres 9.5. This is my setup:

Function wrapper

For repeated use, I would create a function in Postgres 9.5 like this:

PARALLEL SAFE only for Postgres 9.6 or later.

Using a polymorphic input type this works for any array type, not just int[].

Make it IMMUTABLE to allow performance optimization and index expressions.

But don’t make it STRICT, which would disable “function inlining” and impair performance because array_position() is not STRICT itself. See:

If you need to catch the case arr IS NULL:

For Postgres 9.1 use the t_91 expression from above. The rest applies unchanged.

Closely related:

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement