Eindeutigkeitsbeschränkung mit Datumsbereich

15

Betrachten Sie eine pricesTabelle mit diesen Spalten:

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

Ich möchte, dass die Datenbank die Regel erzwingt, dass ein Produkt nur einen Preis zu einer bestimmten Menge in einem Datumsbereich (über where <date> BETWEEN start_date AND end_date) haben kann.

Ist eine solche bereichsbezogene Einschränkung möglich?

Spitze
quelle

Antworten:

23

Ja, Sie können eine EXCLUDEEinschränkung verwenden, bei der es sich um eine Verallgemeinerung von UNIQUEEinschränkungen handelt:

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

Die Einschränkung kann folgendermaßen interpretiert werden:

Lassen Sie nicht zu, dass zwei Zeilen denselben product_id, denselben quantityund überlappenden ( &&) Datumsbereich haben.

Das '[]'ist für den gewünschten All-Inclusive-Datumsbereich (der Standard ist [)für Bereichstypen).

Weitere Informationen finden Sie in der Dokumentation zu Einschränkungen für Bereichstypen . Wahrscheinlich müssen Sie die Erweiterung auch hinzufügen, indem Sie Folgendes ausführen (einmal für jede Datenbank, in der Sie diese installieren möchten):

CREATE EXTENSION btree_gist;
ypercubeᵀᴹ
quelle
Das ist fantastisch. Ich denke nicht, dass daterangees genau dasselbe ist, da es sich um eine exklusive Untergrenze handelt, aber das lässt sich leicht beheben. Sollte ich meine Daten wirklich migrieren, um einen daterangeSpaltentyp zu verwenden (kann dies zu einer separaten Frage machen, wenn dies besser ist), oder ist diese zweispaltige Sache sinnvoll?
Spitze
Der Standardwert für inklusive Untergrenze und exklusive Obergrenze, wenn ich mich recht erinnere. Ich bearbeite für die All Inclusive. Normalerweise bevorzuge ich die Standardeinstellung, wie sie in hotelähnlichen Anwendungen üblich ist. (Ich steige am 2. im Hotel ein, steige am 8. aus, bin 6 Tage geblieben. Die nächste Besatzung kann am 8.
eintreten.
Ich könnte tatsächlich gespiegelt werden, welches ist welches? Ich habe gerade etwas über Sortimentsarten herausgefunden und lese die Dokumente!
Spitze
Ich bin mir nicht sicher, was besser ist, 2 Spalten oder eine mit Daterange. Sie können eine separate Frage stellen. Dies hängt wahrscheinlich von der gewünschten Verwendung, den Abfragen, der Benutzerfreundlichkeit (und den Indexanforderungen) ab. Wenn es separate Spalten gibt, ist es beispielsweise einfacher, einen Index zu haben (product_id, start_date). Bei einer Daterange müsste das ein Index für(product_id, lower(range_column))
ypercubeᵀᴹ