PostgreSQL设置自定义约束

时间:2017-04-17 15:49:30

标签: sql 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"

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

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