Уникальное ограничение Postgres не обеспечивает уникальность

Вот мое ограничение:

CREATE UNIQUE INDEX index_subscriptions_on_user_id_and_class_type_id_and_deleted_at
  ON subscriptions
  USING btree
  (user_id, class_type_id, deleted_at);

Этот запрос доказывает, что ограничение фактически не работает:

SELECT id, user_id, class_type_id,deleted_at
FROM subscriptions;

Вот результат:

enter image description here

Почему уникальность не соблюдается?

+1
источник поделиться
2 ответа

Уникальные индексы в Postgres основаны на равных значениях, но NULL никогда не равен ни одному, включая другие NULL. Поэтому любая строка с значением NULL deleted_at отличается от любой другой возможной строки, поэтому вы можете вставить любое количество из них.

Один из способов - создать частичные индексы, применяя разные правила к строкам с и без 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;
+9
источник

Это происходит из-за значения NULL в столбце created_at. Уникальный индекс (или ограничение) допускает в них несколько строк с NULL.

Единственный способ предотвратить это - либо объявить столбец как NOT NULL, чтобы принудительно присвоить ему значение, либо уменьшить уникальные столбцы до (user_id, class_type_id)

+3
источник

Посмотрите другие вопросы по метке или Задайте вопрос