Utwórz dwa częściowe indeksy :
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;
W ten sposób może istnieć tylko jedna kombinacja (user_id, recipe_id)
gdzie menu_id IS NULL
, skutecznie wdrażając pożądane ograniczenie.
Możliwe wady:
- Nie możesz mieć klucza obcego odwołującego się do
(user_id, menu_id, recipe_id)
. (Wydaje się nieprawdopodobne, abyś potrzebował odniesienia do FK o szerokości trzech kolumn – zamiast tego użyj kolumny PK!) - Nie możesz bazować
CLUSTER
na częściowym indeksie. - Zapytania bez pasującego
WHERE
warunek nie może użyć indeksu częściowego.
Jeśli potrzebujesz kompletnego indeks, możesz alternatywnie upuścić WHERE
warunek z favo_3col_uni_idx
Twoje wymagania są nadal wymuszane.
Indeks, obejmujący teraz całą tabelę, nakłada się na drugi i powiększa się. W zależności od typowych zapytań i procentu NULL
wartości, może to być przydatne lub nie. W ekstremalnych sytuacjach może nawet pomóc w utrzymaniu wszystkich trzech indeksów (dwóch częściowych i sumy na górze).
To dobre rozwiązanie dla pojedynczej kolumny z wartościami null , może dla dwojga. Ale szybko wymyka się z rąk po więcej, ponieważ potrzebujesz oddzielnego indeksu częściowego dla każdej kombinacji kolumn dopuszczających wartość null, więc liczba rośnie dwumianowo. Dla wielu kolumn dopuszczających wartość null , zobacz zamiast tego:
- Dlaczego moje UNIKALNE ograniczenie nie uruchamia się?
Na marginesie:radzę nie używać identyfikatorów mieszanych wielkości liter w PostgreSQL.