SQL 检查具有多个条件的约束
SQL check constraint with multiple conditions
我有一个名为时间表的 table。在那个 table 中,我想为其创建一个约束的 4 列,以便只有以下组合是可能的:
- 如果设置了
user_is
,则 task_schedule_id
必须为空。
- 如果设置了
location_id
或customer_id
,则要求user_id
不为空,并确保location_id
和customer_id
不会同时设置。
- 如果设置了
task_schedule_id
,则要求 user_id
、customer_id
和 location_id
为空。
这是table:
CREATE TABLE IF NOT EXISTS timesheets
(
id uuid NOT NULL DEFAULT gen_random_uuid(),
created_at timestamptz NOT NULL DEFAULT current_timestamp,
updated_at timestamptz NOT NULL DEFAULT current_timestamp,
deleted_at timestamptz NULL,
-- Where and who (check if location_id or customer_id is set then require user)
location_id uuid NULL,
customer_id uuid NULL,
user_id uuid NULL,
-- Or what... BUT not both
task_schedule_id uuid NULL,
-- Billing
billable bool NOT NULL DEFAULT TRUE,
billed_at timestamptz NULL,
-- fks and pk
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (task_schedule_id) REFERENCES task_schedules (id),
FOREIGN KEY (location_id) REFERENCES locations (id),
FOREIGN KEY (customer_id) REFERENCES customers (id),
PRIMARY KEY (id)
);
这是我目前所拥有的:
ALTER TABLE timesheets
ADD constraint only_one_group
check (
((user_id is null and customer_id is null and location_id is null) and
task_schedule_id is not null)
or
(user_id is not null and not (customer_id is null and location_id is null) and
(customer_id is null or location_id is null) and
task_schedule_id is null)
);
上下文是 task_schedule 链接到可以包含 location_id 和/或 customer_id 的任务。这个想法是时间表可以全局创建或与任务结合创建。
您可以将约束写为:
ALTER TABLE timesheets
ADD constraint just_user__or__location_or_customer_with_user__or__just_task check (
(
user_id is not null
and task_schedule_id is null
and (
(location_id is null and customer_id is null)
and (location_id is not null or customer_id is not null)
)
) or (
(location_id is not null or customer_id is not null)
and not (location_id is not null and customer_id is not null)
and user_id is not null
) or (
task_schedule_id is not null
and user_id is null
and location_id is null
and customer_id is null
)
);
我有一个名为时间表的 table。在那个 table 中,我想为其创建一个约束的 4 列,以便只有以下组合是可能的:
- 如果设置了
user_is
,则task_schedule_id
必须为空。 - 如果设置了
location_id
或customer_id
,则要求user_id
不为空,并确保location_id
和customer_id
不会同时设置。 - 如果设置了
task_schedule_id
,则要求user_id
、customer_id
和location_id
为空。
这是table:
CREATE TABLE IF NOT EXISTS timesheets
(
id uuid NOT NULL DEFAULT gen_random_uuid(),
created_at timestamptz NOT NULL DEFAULT current_timestamp,
updated_at timestamptz NOT NULL DEFAULT current_timestamp,
deleted_at timestamptz NULL,
-- Where and who (check if location_id or customer_id is set then require user)
location_id uuid NULL,
customer_id uuid NULL,
user_id uuid NULL,
-- Or what... BUT not both
task_schedule_id uuid NULL,
-- Billing
billable bool NOT NULL DEFAULT TRUE,
billed_at timestamptz NULL,
-- fks and pk
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (task_schedule_id) REFERENCES task_schedules (id),
FOREIGN KEY (location_id) REFERENCES locations (id),
FOREIGN KEY (customer_id) REFERENCES customers (id),
PRIMARY KEY (id)
);
这是我目前所拥有的:
ALTER TABLE timesheets
ADD constraint only_one_group
check (
((user_id is null and customer_id is null and location_id is null) and
task_schedule_id is not null)
or
(user_id is not null and not (customer_id is null and location_id is null) and
(customer_id is null or location_id is null) and
task_schedule_id is null)
);
上下文是 task_schedule 链接到可以包含 location_id 和/或 customer_id 的任务。这个想法是时间表可以全局创建或与任务结合创建。
您可以将约束写为:
ALTER TABLE timesheets
ADD constraint just_user__or__location_or_customer_with_user__or__just_task check (
(
user_id is not null
and task_schedule_id is null
and (
(location_id is null and customer_id is null)
and (location_id is not null or customer_id is not null)
)
) or (
(location_id is not null or customer_id is not null)
and not (location_id is not null and customer_id is not null)
and user_id is not null
) or (
task_schedule_id is not null
and user_id is null
and location_id is null
and customer_id is null
)
);