I have these tables in my PostgreSQL database:
CREATE TABLE companies (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE
);
-- Employees belong to one company
CREATE TABLE employees (
id INT PRIMARY KEY,
companyId INT NOT NULL,
employeeName VARCHAR(255) NOT NULL,
FOREIGN KEY (companyId) REFERENCES companies(id)
);
-- Projects Belong to one company
CREATE TABLE projects (
id INT PRIMARY KEY,
companyId INT NOT NULL,
projectName VARCHAR(255) NOT NULL,
FOREIGN KEY (companyId) REFERENCES companies(id)
);
Now I need to create a table that links an employee to a project:
-- The linking table (with the problem)
CREATE TABLE assignments (
id INT PRIMARY KEY,
employeeId INT NOT NULL,
projectId INT NOT NULL,
FOREIGN KEY (employeeId) REFERENCES employees(id),
FOREIGN KEY (projectId) REFERENCES projects(id)
);
The issue is that an employee from one company, can be linked to a project from another company, which I do not want.
How do I enforce the employee and project to be from the same company?
The clean SQL solution is to add redundant unique constraints that include the companyid
to projects
and employees
and reference those with the foreign keys:
ALTER TABLE projects ADD UNIQUE (companyid, id);
ALTER TABLE employees ADD UNIQUE (companyid, id);
CREATE TABLE assignments (
id INT PRIMARY KEY,
employeeid INT NOT NULL,
projectid INT NOT NULL,
companyid INT NOT NULL,
FOREIGN KEY (companyid, employeeid) REFERENCES employees(companyid, id),
FOREIGN KEY (companyid, projectid) REFERENCES projects(companyid, id)
);
The extra unique index is of course painful, but a consolation is that you should have an index on companyid
anyway if you ever want to delete a row in companies
.