How can I enforce the following business logic in my database schema, without using application code:
- a user must belong to exactly one company
- a company can have multiple vehicles
- a vehicle can have multiple companies
- a user can have multiple vehicles, but these vehicles must be a subset of the vehicles that are linked to the user’s company (i.e. a user cannot be linked to a vehicle that it’s company does not have access to)
This is what I have so far:
create table companies (
id serial primary key,
name varchar not null,
unique(name)
);
create table vehicles (
id serial primary key,
name varchar not null,
unique(name)
);
create table users (
id serial primary key,
company_id integer not null,
name varchar not null,
foreign key (company_id) references companies(id)
);
create table vehicle_companies (
id serial primary key,
vehicle_id integer not null,
company_id integer not null,
foreign key (vehicle_id) references vehicles(id),
foreign key (company_id) references companies(id)
);
create table user_vehicles (
user_id integer not null,
vehicle_company_id integer not null,
foreign key (user_id) references users(id),
foreign key (vehicle_company_id) references vehicle_companies(id)
);
How can I ensure that all times the rows in the user_vehicles
table only reference vehicle_companies
records that have a company_id
which is the same as their referenced users
table records’ company_id
?
I am using postgres.
2
Answers
This schema solved it for me:
DB fiddle
You are trying enforce referential integrity across independent entities (tables). You cannot do that with simple constraints (perhaps an Exclude Constraint – but I do not think so). To accomplish that you will need a trigger on
user_vehicles
.I have put together a short demo here, with very simple data values.