2017-04-17 75 views
1

我有一個約會的表這種結構(分塊的可讀性):PostgreSQL的設置自定義約束

appointments: 
- id 
- staff_id 
- start_time 
- end_time 
- cancelled 

我想添加一個數據庫約束不能夠翻一番預訂約會。我在想,如果有可能的線沿線的添加約束條件:

when staff_id = ? and cancelled = false then set a "unique" constraint on start_time

如果這是不可能有類似的東西我可以做實現我的最終目標?

編輯

這是全預約表

CREATE TABLE "appointments" (
      "id" uuid, 
      "customer_id" uuid NOT NULL REFERENCES customers ON DELETE CASCADE ON UPDATE CASCADE, 
      "staff_id" uuid NOT NULL REFERENCES staff ON DELETE CASCADE ON UPDATE CASCADE, 
      "start_time" timestamp NOT NULL, 
      "end_time" timestamp NOT NULL, 
      "notes" text, 
      "cancelled" boolean NOT NULL DEFAULT false, 
      "created_at" timestamp with time zone NOT NULL, 
      "updated_at" timestamp with time zone NOT NULL, 
     ); 

用排除法:

CREATE TABLE "appointments" (
     "id" uuid, 
     "customer_id" uuid NOT NULL REFERENCES customers ON DELETE CASCADE ON UPDATE CASCADE, 
     "staff_id" uuid NOT NULL REFERENCES staff ON DELETE CASCADE ON UPDATE CASCADE, 
     "start_time" timestamp NOT NULL, 
     "end_time" timestamp NOT NULL, 
     "notes" text, 
     "cancelled" boolean NOT NULL DEFAULT false, 
     "created_at" timestamp with time zone NOT NULL, 
     "updated_at" timestamp with time zone NOT NULL, 
     EXCLUDE USING gist (
      staff_id WITH =, 
      tsrange(start_time, end_time) WITH && 
     ) WHERE (NOT cancelled), 
     PRIMARY KEY ("id") 
    ); 

與排除錯誤執行:

data type uuid has no default operator class for access method "gist"

+0

爲您所請求的選擇答案不工作。 [請參閱此答案,瞭解如何實際停止使用排除約束進行雙重預訂。](http://stackoverflow.com/a/43456174/124486) –

回答

2

您需要排除約束來停止約會的雙重預約。所選答案中的方法只會停止兩個約會具有相同的開始時間。如果它在第一次約會之後開始,它不會阻止一個約會重疊。

CREATE TABLE appointments (
    id   serial PRIMARY KEY, 
    staff_id int, 
    start_time timestamp, 
    end_time timestamp, 
    cancelled bool DEFAULT false, 
    EXCLUDE USING gist (
    staff_id WITH =, 
    tsrange(start_time, end_time) WITH && 
) WHERE (NOT cancelled) 
); 

現在你不能預約預約。

INSERT INTO appointments (staff_id, start_time, end_time) VALUES 
    (1, '01-01-2010T07:30', '01-01-2010T09:30'), 
    (1, '01-01-2010T08:00', '01-01-2010T09:45') 
; 

ERROR: conflicting key value violates exclusion constraint "appointments_staff_id_tsrange_excl" 
DETAIL: Key (staff_id, tsrange(start_time, end_time))=(1, ["2010-01-01 08:00:00","2010-01-01 09:45:00")) conflicts with existing key (staff_id, tsrange(start_time, end_time))=(1, ["2010-01-01 07:30:00","2010-01-01 09:30:00")). 

您也可以刪除start_timeend_time,並把它們都作爲timestamp-ranges

+0

這正是我要找的;然而,我得到的錯誤'列「可以」在關鍵字不存在'應該'可以'是start_time? – Rodrigo

+0

@Rodrigo更新了它。我正在修復它的謂詞取消。我最初錯過了。 –

+0

我是否需要任何特殊擴展來使用gist?我得到錯誤'數據類型文本沒有默認的操作員類的訪問方法「要求' – Rodrigo

1
create unique index the_index on appointments (staff_id, start_time) 
where not cancelled; 
+1

這實際上並不會阻止預約被雙重預訂。 [請參閱此答案以瞭解如何使用排除約束來停止雙重預訂。](http://stackoverflow.com/a/43456174/124486) –

+0

@EvanCarroll問題中缺少需求。 –

+1

*我想添加一個數據庫約束,以避免雙重約會。*「雙重書籍」通常意味着任何衝突。不僅僅是開始時間的衝突。 –