Purtroppo, questo non può essere risolto facilmente con semplici contrappunti/indici unici (se può essere risolto con loro affatto).
Quello che vi serve, è un exclusionconstraint: la possibilità di escludere alcune righe, sulla base di qualcosa come collisione. I vincoli unici sono solo specifici vincoli di esclusione (sono basati sull'uguaglianza collisioni).
Quindi, in teoria, è sufficiente per escludere ogni row1
, dove c'è già un row2
, per il quale questa espressione è vero: ARRAY[row1.cola, row1.colb] && ARRAY[row2.cola, row2.colb]
Questo indice potrebbe fare il lavoro (supporto attualmente solo gist
indici vincoli di esclusione):
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((ARRAY[cola, colb]) WITH &&);
Ma purtroppo, non esiste una categoria operatore predefinito per le matrici (che utilizza gist
). C'è uno intarray
module, che fornisce uno solo per gli array integer
, ma nulla per gli array text
.
Se davvero si vuole lavorare su questo, si può sempre abusare del range
types (p.es. ho usato il adiacente -|-
dell'operatore, che gestisce tutti i casi, che non possono essere trattate con unique
) ...
-- there is no built-in type for text ranges neither,
-- but it can can be created fairly easily:
CREATE TYPE textrange AS RANGE (
SUBTYPE = text
);
ALTER TABLE table_name
ADD CONSTRAINT table_name_exclusion
EXCLUDE USING gist ((textrange(least(cola, colb), greatest(cola, colb))) WITH -|-);
-- the exclusion constraint above does not handle all situations:
ALTER TABLE table_name
ADD CONSTRAINT table_name_check
CHECK (cola is distinct from colb); -- without this, empty ranges could be created,
-- which are not adjacent to any other range
CREATE UNIQUE INDEX table_name_unique
ON table_name ((ARRAY[least(cola, colb), greatest(cola, colb)]));
-- without this, duplicated rows could be created,
-- because ranges are not adjacent to themselves
... ma temo, il tuo problema originale potrebbe essere risolto molto più facilmente con un piccolo refactoring del database; che ci porta alla domanda: quale problema, vuoi risolvere con questo?