PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Prevenire voci adiacenti/sovrapposte con EXCLUDE in PostgreSQL

I tipi di intervallo sono costituiti da un bordo inferiore e uno superiore, che possono essere inclusi o esclusi. Il tipico caso d'uso (e predefinito per i tipi di intervallo) è includere inferiore ed escludi il limite superiore.

Escluso sovrapposizione le gamme sembrano chiare. C'è un bell'esempio di codice nel manuale

Inoltre, crea un altro vincolo di esclusione utilizzando l'operatore adiacente -|- per escludere anche adiacente inserimenti. Entrambi devono essere basati su GiST index poiché GIN non è attualmente supportato per questo.

Per mantenerlo pulito, imporrei [) limiti (incluso inferiore ed escluso superiore) per tutte le voci con un CHECK vincolo usando le funzioni di intervallo:

CREATE TABLE tbl (
   tbl_id serial PRIMARY KEY
 , tsr tsrange
 , CONSTRAINT tsr_no_overlap  EXCLUDE USING gist (tsr WITH &&)
 , CONSTRAINT tsr_no_adjacent EXCLUDE USING gist (tsr WITH -|-)
 , CONSTRAINT tsr_enforce_bounds CHECK (lower_inc(tsr) AND NOT upper_inc(tsr))
);

db<>gioca qui
(vecchio violino SQL)

Purtroppo, questo crea due identici indici GiST per implementare entrambi i vincoli di esclusione, dove uno sarebbe sufficiente, logicamente. Questa sembra essere una lacuna dell'attuale implementazione (fino almeno a Postgres 11).