Создать два частичных индекса :
CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
Таким образом, может быть только одна комбинация (user_id, recipe_id)
, где menu_id IS NULL
, эффективно реализующая желаемое ограничение.
Возможные недостатки: у вас не может быть внешнего ключа, ссылающегося на (user_id, menu_id, recipe_id)
, вы не можете основывать CLUSTER
на частичном индексе, а запросы без соответствующего условия WHERE
не могут использовать частичный индекс. (Кажется маловероятным, что вы захотите, чтобы FK ссылался на три столбца - используйте вместо этого столбец PK).
Если вам нужен индекс complete , вы также можете удалить условие WHERE
с favo_3col_uni_idx
, и ваши требования по-прежнему выполняются.
Индекс, теперь включающий всю таблицу, перекрывается с другим и становится больше. В зависимости от типичных запросов и процента значений NULL
это может быть или не быть полезным. В экстремальных ситуациях это может даже помочь сохранить все три индекса (два частичных и общее число сверху).
Помимо: я советую не использовать идентификаторы смешанного регистра в PostgreSQL .