I have a table called timesheets. In that table there are 4 columns for which I want to create a constraint so that only the following combinations are possible:
- If
user_is
is set thentask_schedule_id
must be null. - If
location_id
orcustomer_id
is set, then requireuser_id
to be not null and ensure that not bothlocation_id
andcustomer_id
are set. - If
task_schedule_id
is set then requireuser_id
,customer_id
andlocation_id
to be null.
This is the 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)
);
And this is what I have so far:
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)
);
The context is that a task_schedule links to a task which can contain a location_id and or a customer_id. The idea is that timesheets can be created globally or in combination with tasks.