Is there any difference between a null value and a row type where all columns are null? Postgres queries appear to be able to tell the difference (displaying null columns rather than a blank) and I want to know if there's anything I should be aware of. e.g.
CREATE TYPE node AS (
rank integer
, id integer
);
CREATE TABLE hierarchy (
node node
);
INSERT INTO hierarchy (node) VALUES (null);
INSERT INTO hierarchy (node) VALUES ((null, null));
SELECT *, node IS NULL AS check_null FROM hierarchy;
node | check_null ------+------------ | t (,) | t
Is there any difference between a null value and a rowtype where all the columns are null?
NULL:node
is still distinct from (null, null)::node
:
SELECT null::node IS DISTINCT FROM (null, null)::node AS dist;
dist ---- t
I agree this is confusing. And the manual might be sharpened here, too:
For non-null inputs,
IS DISTINCT FROM
is the same as the<>
operator. However, if both inputs are null it returns false, and if only one input is null it returns true.
Turns out to be slightly incorrect in the face of above demo. Even though there is a hint further down:
If the
expression
is row-valued, thenIS NULL
is true when the row expression itself is null or when all the row's fields are null.
So we have two distinct cases in which a row value is null:
It should be mentioned that these two cases are still considered distinct, when compared with IS DISTINCT FROM
. May be worth a documentation bug report ...
anything I should be aware of?
Yes. Wherever DISTINCT
comes into play, both variants are considered, well, distinct:
SELECT DISTINCT * FROM hierarchy;
node1 ------ (,) (2 rows)
Note the 2nd invisible row, because psql displays null values this way.
To stop the (,) case from occurring ?
Addressing your comment:
CREATE TABLE hierarchy (
node node CHECK (node IS DISTINCT FROM (null, null)::node)
);
Note two things:
(null, null)::node
is necessary.