Postgres unique indexes are based on equal values, but NULL is never equal to any, including other NULLs. Therefore, any row with a NULL value deleted_at is different from any other possible row, so you can insert any number of them.
One way is to create partial indexes by applying different rules to rows with and without NULL:
CREATE UNIQUE INDEX ... ON subscriptions (user_id, class_type_id) WHERE deleted_at IS NULL; CREATE UNIQUE INDEX ... ON subscriptions (user_id, class_type_id, deleted_at) WHERE deleted_at IS NOT NULL;
IMSoP May 03 '14 at 20:12 2014-05-03 20:12
source share