Създайте два частични индекса :
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). (Изглежда малко вероятно да искате препратка към FK три колони широка - вместо това използвайте колоната PK!) - Не можете да базирате
CLUSTERна частичен индекс. - Заявки без съответстващ
WHEREусловието не може да използва частичния индекс.
Ако имате нужда от пълен index, можете алтернативно да пуснете WHERE условие от favo_3col_uni_idx и вашите изисквания все още се прилагат.
Индексът, който сега включва цялата таблица, се припокрива с другия и става по-голям. В зависимост от типичните заявки и процента на NULL стойности, това може да е полезно или не. В екстремни ситуации може дори да помогне да се поддържат и трите индекса (двата частични и общия отгоре).
Това е добро решение за единична колона с нула , може и за двама. Но той бързо излиза от ръцете за повече, тъй като имате нужда от отделен частичен индекс за всяка комбинация от колони с нула, така че броят нараства биномно. За множество колони с нулеви стойности , вижте вместо това:
- Защо моето ограничение UNIQUE не се задейства?
Настрана:Съветвам ви да не използвате смесени идентификатори в PostgreSQL.