Maak twee gedeeltelijke indexen :
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;
Op deze manier kan er maar één combinatie zijn van (user_id, recipe_id)
waar menu_id IS NULL
, waardoor de gewenste beperking effectief wordt geïmplementeerd.
Mogelijke nadelen:
- U mag geen refererende sleutel hebben die verwijst naar
(user_id, menu_id, recipe_id)
. (Het lijkt onwaarschijnlijk dat u een FK-referentie van drie kolommen breed wilt hebben - gebruik in plaats daarvan de PK-kolom!) - Je kunt
CLUSTER
niet baseren op een gedeeltelijke index. - Zoekopdrachten zonder een overeenkomende
WHERE
voorwaarde kan de gedeeltelijke index niet gebruiken.
Als u een volledige . nodig heeft index, kunt u ook de WHERE
voorwaarde van favo_3col_uni_idx
en uw vereisten worden nog steeds afgedwongen.
De index, die nu de hele tabel omvat, overlapt met de andere en wordt groter. Afhankelijk van typische zoekopdrachten en het percentage NULL
waarden, kan dit al dan niet nuttig zijn. In extreme situaties kan het zelfs helpen om alle drie de indexen te behouden (de twee gedeeltelijke en een totaal bovenaan).
Dit is een goede oplossing voor een enkele nullable kolom , misschien voor twee. Maar voor meer loopt het snel uit de hand, omdat je een aparte gedeeltelijke index nodig hebt voor elke combinatie van nullable-kolommen, dus het aantal groeit binomiaal. Voor meerdere kolommen met nullwaarden , zie in plaats daarvan:
- Waarom wordt mijn UNIQUE-beperking niet geactiveerd?
Terzijde:ik adviseer om geen hoofdletter-ID's te gebruiken in PostgreSQL.