Update
Postgres 15 added NULLS NOT DISTINCT
for UNIQUE
constraints and indexes. See:
Original answer
My guess is you are missing the fact that NULL
values are considered to be distinct, i.e., do not conflict with a UNIQUE
constraint. If you enter:
(NULL, 1, 20)
for (name, id, age)
multiple times, you get no unique violation. Two NULL
values are not considered "the same" (i.e. "distinct").
You can either set all involved columns NOT NULL
(after replacing NULL
values with dummy values).
Or you can implement additional partial indexes to cover NULLs (after cleaning up "dupes" with NULL
). For instance, if you need to cover the name
column for NULLs:
CREATE UNIQUE INDEX tbl_id_age_name_null_idx ON my_table (id, age)
WHERE name IS NULL;
Then you can have:
('pete', 1, 20)
, ('jane', 1, 20)
, (NULL , 1, 20)
for (name, id, age)
in your table, but none of these a second time. See: