2017-04-17 53 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

*我想添加一个数据库约束,以避免双重约会。*“双重书籍”通常意味着任何冲突。不仅仅是开始时间的冲突。 –