Vincolo di unicità con intervallo di date


15

Prendi in considerazione una pricestabella con queste colonne:

id         integer primary key
product_id integer -- foreign key
start_date date not null
end_date   date not null
quantity   integer
price      numeric

Vorrei che il database imponesse la regola secondo cui un prodotto può avere un solo prezzo per una quantità specifica in un intervallo di date (via where <date> BETWEEN start_date AND end_date).

È possibile questo tipo di vincolo basato sull'intervallo?

Risposte:


23

Sì, è possibile utilizzare un EXCLUDEvincolo, che è una generalizzazione dei UNIQUEvincoli:

ALTER TABLE prices 
  ADD CONSTRAINT unique_price_per_product_quantity_daterange
    EXCLUDE  USING gist
    ( product_id WITH =, 
      quantity WITH =, 
      daterange(start_date, end_date, '[]') WITH &&   -- this is the crucial
    );

Il vincolo può essere interpretato nel modo seguente:

Non consentire due righe con intervalli di date uguali product_id, uguali quantitye sovrapposti ( &&).

Il '[]'è per il voluto intervallo di date all-inclusive (il valore predefinito è [)per i tipi di gamma).

Vedere la documentazione sui vincoli per i tipi di intervallo . Probabilmente dovrai anche aggiungere l'estensione eseguendo (una volta, per ogni database in cui desideri installarlo):

CREATE EXTENSION btree_gist;

Questo e spettacolare. Non penso che daterangesia esattamente lo stesso dal momento che ha un limite inferiore esclusivo, ma è facile da risolvere. Dovrei davvero migrare i miei dati per utilizzare un daterangetipo di colonna (può fare una domanda separata se è meglio) o è ragionevole questa cosa a due colonne?
picco

L'impostazione predefinita in limite inferiore compreso e limite superiore esclusivo, se ricordo bene. Modificherò per il tutto compreso. Di solito preferisco l'impostazione predefinita in quanto è comune nelle applicazioni simili ad un hotel. (Arrivo in hotel al 2 °,
scendo

Potrei davvero essere capovolto su quale è che ... Ho appena scoperto i tipi di intervallo oggi e sto leggendo i documenti!
picco

Non sono sicuro di cosa sia preferibile, 2 colonne o una con daterange. Puoi fare una domanda separata. Probabilmente dipenderà dall'uso desiderato, dalle query, dalla facilità d'uso (e dalle esigenze dell'indice). Se ci sono colonne separate, ad esempio sarebbe più facile avere un indice attivo (product_id, start_date). Con un daterange, quello dovrebbe essere un indice su(product_id, lower(range_column))
ypercubeᵀᴹ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.