Opret to delvise indekser :
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;
På denne måde kan der kun være én kombination af (user_id, recipe_id)
hvor menu_id IS NULL
, der effektivt implementerer den ønskede begrænsning.
Mulige ulemper:
- Du kan ikke have en fremmednøgle, der henviser til
(user_id, menu_id, recipe_id)
. (Det virker usandsynligt, at du vil have en FK-reference i tre kolonner bred - brug PK-kolonnen i stedet!) - Du kan ikke basere
CLUSTER
på et delvist indeks. - Forespørgsler uden en matchende
WHERE
betingelse kan ikke bruge det delvise indeks.
Hvis du har brug for en komplet indeks, kan du alternativt droppe WHERE
betingelse fra favo_3col_uni_idx
og dine krav er stadig håndhævet.
Indekset, der nu omfatter hele tabellen, overlapper med det andet og bliver større. Afhængigt af typiske forespørgsler og procentdelen af NULL
værdier, kan dette være nyttigt eller ikke. I ekstreme situationer kan det endda hjælpe at opretholde alle tre indekser (de to delvise og en total på toppen).
Dette er en god løsning til en enkelt nullbar kolonne , måske for to. Men det kommer hurtigt ud af hænderne for mere, da du har brug for et separat delvist indeks for hver kombination af nullbare kolonner, så antallet vokser binomalt. For flere nullbare kolonner , se i stedet:
- Hvorfor udløses min UNIQUE begrænsning ikke?
Bortset fra:Jeg anbefaler ikke at bruge id'er med blandede store og små bogstaver i PostgreSQL.