预订表中仅允许工作时间

And*_*rus 2 sql postgresql database-design schedule postgresql-9.2

PostgreSql 9.2 保留表定义为

CREATE EXTENSION btree_gist;
CREATE TABLE schedule (
  id serial primary key,
  during tsrange not null,
  EXCLUDE USING gist (during WITH &&)
);
Run Code Online (Sandbox Code Playgroud)

假期见表

CREATE TABLE holiday ( day primary key );
Run Code Online (Sandbox Code Playgroud)

工作日工作时间为 8:00 至 18:00,且只能以 30 分钟为间隔进行预订。如何向 while 值添加约束,以便仅允许在工作时间进行预订:

  1. tsrange 中的开始日期和结束日期始终相同。
  2. 开始和结束日期不能是星期六和星期日
  3. 开始和结束日期不能出现在公共假期表中
  4. 开始时间只能为 8:00、8:30、9:00、9:30、... 16:00、16:30、17:00 或 17:30(含)
  5. 结束时间只能为 8:30、9:00、9:30、... 16:00、16:30、17:00、17:30 或 18:00(不含)

将这些或其中一些约束添加到该表中是否合理?如果有,如何添加?如果有帮助的话,可以更改计划表结构。

Erw*_*ter 5

您可以使用简单的CHECK约束解决除第 3 项之外的所有问题:

使用专用范围函数 lower(anysrange)upper(anyrange)访问范围的下限/上限。

1.) tsrange 中的开始日期和结束日期始终相同。

CONSTRAINT schedule_same_day
CHECK (lower(during)::date = upper(during)::date)
Run Code Online (Sandbox Code Playgroud)

2.) 开始和结束日期不能是周六和周日

使用isodow, 不是dow为了更简单的表达。

CONSTRAINT schedule_no weekend
CHECK (EXTRACT(ISODOW FROM lower(during)) < 6)  -- upper is on same day
Run Code Online (Sandbox Code Playgroud)

3.) 开始和结束日期不能出现在公共假期表中

为此,您需要一个触发器,例如:

CONSTRAINT schedule_same_day
CHECK (lower(during)::date = upper(during)::date)
Run Code Online (Sandbox Code Playgroud)

4.) 开始时间只能为 8:00、8:30、9:00、9:30、...、16:00、16:30、17:00 或 17:30(含)。
5.) 结束时间只能是 8:30、9:00、9:30、...、16:00、16:30、17:00、17:30 或 18:00(不含)。

CONSTRAINT schedule_no weekend
CHECK (EXTRACT(ISODOW FROM lower(during)) < 6)  -- upper is on same day
Run Code Online (Sandbox Code Playgroud)

更新:在Postgres 14或更高版本中使用date_bin()

CREATE OR REPLACE FUNCTION trg_during_no_holy()
  RETURNS trigger
  LANGUAGE plpgsql AS
$func$
BEGIN
   IF EXISTS (SELECT FROM holiday WHERE day = lower(NEW.during)) THEN
      RAISE EXCEPTION 'Day too holy: %', lower(NEW.during);
   END IF;

   RETURN NEW;
END
$func$;

CREATE TRIGGER insupbef_holycheck
  BEFORE INSERT OR UPDATE
  ON schedule
  FOR EACH ROW
  EXECUTE PROCEDURE trg_during_no_holy();
Run Code Online (Sandbox Code Playgroud)

这也强制执行您的附加要求“限制秒和小数秒”

看: