Given the following query
select *
from jsonb_to_recordset('[{"a":1},{"a":2,"b":42}]') i(a int, b int)
where i is not null
I observe the result of a single row, which is the one where both columns are non-null.
When negating the where clause to be where i is null
, I instead observe the empty result set.
I’m somewhat confused by the first version of that query not resulting in both rows, and by negating the comparison not yielding the complement of the set returned by the first query.
So far I’ve not been able to find the right place in the documentation where this behaviour is described, and would appreciate any pointers in the right direction to better understand what’s happening.
For context, this came up for me when trying to check whether or not there was a matching row in an outer join. To avoid the above somewhat surprising behaviour, I opted to instead check for one of the non-nullable columns of the joined relation to be null/not null, which fixed my immediate problem, but makes me wonder if there’s perhaps a better way to perform this kind of check that’d always work, even if all the columns of the relation you’re joining are nullable, and without having to enumerate all of the columns and relying on at least one of them to be non-null.
2
Answers
The rule is quite obvious
for
i(a int, b int)
i is not null
->a is not null and b is not null
i is null
->a is null and b is null
With query
output is
and possible check’s
3.NOT (i is null)
4.NOT (i is not null)
5.null and not null
This is documented at https://www.postgresql.org/docs/current/functions-comparison.html for row types (also known as composite types):
You can generate yourself a cheat sheet using
(online demo)
So for checking whether a row got matched in an outer join, you should use
IS DISTINCT FROM NULL
.