Contrainte d'unicité avec plage de dates


15

Considérez un pricestableau 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?

Réponses:


23

Oui, vous pouvez utiliser une EXCLUDEcontrainte, qui est une généralisation des UNIQUEcontraintes:

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:

N'autorisez pas deux lignes qui ont des plages de dates identiques product_id, identiques quantityet se chevauchant ( &&).

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

Voir la documentation sur les 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;

C'est génial. Je ne pense pas que ce daterangesoit exactement la même chose car c'est une limite inférieure exclusive, mais c'est facile à corriger. Dois-je vraiment migrer mes données pour utiliser un daterangetype de colonne (peut en faire une question distincte si c'est mieux) ou cette chose à deux colonnes est-elle raisonnable?
pic

La valeur par défaut en borne inférieure inclusive et borne supérieure exclusive, si je me souviens bien. Je vais modifier pour le tout compris. Je préfère généralement la valeur par défaut car elle est courante dans les applications de type hôtel. (J'arrive à l'hôtel le 2, je
descends

Je pourrais en fait être retourné sur ce qui est qui ... je viens de découvrir les types de gamme aujourd'hui et je lis les documents!
pic

Je ne suis pas sûr de ce qui est préférable, 2 colonnes ou une avec daterange. Vous pouvez poser une question distincte. Cela dépendra probablement de l'utilisation que vous souhaitez, des requêtes, de la facilité d'utilisation (et des besoins d'indexation). S'il y a des colonnes séparées, il serait plus facile par exemple d'avoir un index dessus (product_id, start_date). Avec une daterange, cela devrait être un indice le(product_id, lower(range_column))
ypercubeᵀᴹ
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.