web-dev-qa-db-fra.com

Contrainte d'unicité avec plage de dates

Considérez une table prices avec ces colonnes:

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

J'aimerais que la base de données applique la règle selon laquelle un produit ne peut avoir qu'un seul prix pour une quantité spécifique dans une plage de dates (via where <date> BETWEEN start_date AND end_date).

Ce type de contrainte basée sur la plage est-il faisable?

15
spike

Oui, vous pouvez utiliser une contrainte EXCLUDE, qui est une généralisation des contraintes UNIQUE:

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
    );

La contrainte peut être interprétée comme disant:

Ne pas autoriser deux lignes qui ont le même product_id, même quantity et se chevauchant (&&) plages de dates.

Le '[]' correspond à la plage de dates tout compris souhaitée (la valeur par défaut est [) pour les types de plage).

Voir la documentation sur contraintes sur les types de plage . Vous devrez probablement également ajouter l'extension en exécutant (une fois, pour chaque base de données où vous souhaitez que cela soit installé):

CREATE EXTENSION btree_Gist;
23
ypercubeᵀᴹ