Пользовательское ограничение уникального столбца, применяется только в том случае, если один столбец имеет определенное значение

19

Можно ли иметь собственное ограничение уникального столбца следующим образом? Предположим, у меня есть два столбца subsetи typeобе строки (хотя типы данных, вероятно, не имеют значения).

Если typeэто "правда", то я хочу, чтобы комбинация typeи subsetбыла уникальной. В противном случае, нет никаких ограничений. Я использую PostgreSQL 8.4 на Debian.

Фахим Митха
источник

Ответы:

31

Другими словами, вы хотите subsetбыть уникальным, если type = 'true'. Частичный уникальный индекс будет делать это:

CREATE UNIQUE INDEX tbl_some_name_idx ON tbl (subset) WHERE type = 'true';

Таким образом, вы даже можете создавать комбинации с NULLуникальным, что невозможно в противном случае - как подробно описано в этом связанном ответе:
ограничение для нескольких столбцов PostgreSQL и значения NULL

Эрвин Брандштеттер
источник
Спасибо Эрвин. Я не видел эту опцию, когда я смотрел на документацию. Более прямая ссылка - postgresql.org/docs/current/interactive/indexes-partial.html . Смотрите Пример 11-3.
Фахим Митха
@FaheemMitha: Я связал один уровень выше, так как вам нужно объединить в частичный индекс с уникальным индексом .
Эрвин Брандштеттер
1
@ Erwin На этой странице (о частичных индексах) есть пример с частичным уникальным индексом.
ypercubeᵀᴹ
@ypercube: Ах да. Это лучшая ссылка. Я изменил свой ответ, чтобы указать на эту последнюю главу.
Эрвин Брандштеттер,
6

Это дополняет ответ Эрвина выше, но PostgreSQL поддерживает несколько типов индексов. Они, как правило, не являются взаимоисключающими. Вы можете думать о них как о:

  • Индексный метод (btree, GiST, GIN и т. Д.). Выберите один, если необходимо (btree по умолчанию)
  • Частичное или полное. При частичном использовании предложения where
  • Прямой или функциональный. Вы можете индексировать вывод функций.
  • Уникальный или не уникальный

Все это можно комбинировать различными способами. Все, что вы делаете здесь, - это использование уникальных и частичных функций, так что вы получаете частичные уникальные индексы (которые, как вы выяснили, чрезвычайно полезны).

Но предположим, что вы хотите иметь нечувствительный к регистру индекс в поле подмножества, где тип равен true. Затем вы бы добавили функциональное определение:

CREATE INDEX my_index_name_idx_u ON tbl (lower(subset)) WHERE type;

Обратите внимание, что это создает уникальный индекс на выходе функции lower (), вызываемой для атрибута subset, где тип - true.

Крис Траверс
источник
Таким образом, индекс в ответе Эрвина является прямым, в то время как индекс в вашем примере в функциональном, правильный?
Фахим Митха
@FaheemMitha: правильно.
Эрвин Брандштеттер