You can add a multicolumn foreign key to select not just the id of the staff, but also the assigned hotel_id
inside your hotel
table. This would result in a weird looking table structure like this:
Hotel
- Id
- Name
- Manager_Id
- Hotel_Id
Staff
- Id
- Hotel_Id
- IsManager
- Firstname
- Lastname
This is specially looking weird as you have the same id in the Hotel
table twice. And for that to work correctly, you have to add triggers to verify that the Id
and Hotel_Id
value are the same, when the Hotel_Id
column is used. And since you have some kind of circle references (Staff
references the Hotel
table via Hotel_Id
, Hotel
references the Staff
table via Manager_Id
) you have to run ALTER TABLE
statements to add the additional columns Manager_Id
and Hotel_Id
. The queries might look like this:
CREATE TABLE Hotel
(
Id INT AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(30)
);
CREATE TABLE Staff
(
Id INT AUTO_INCREMENT PRIMARY KEY,
Hotel_Id INT NOT NULL,
FirstName VARCHAR(30),
LastName VARCHAR(30),
FOREIGN KEY (Hotel_Id) REFERENCES Hotel(Id),
INDEX (Id, Hotel_Id)
);
The second index is used for the foreign key in the Hotel
table:
ALTER TABLE Hotel ADD Manager_ID INT NULL;
ALTER TABLE Hotel ADD Hotel_ID INT NULL;
ALTER TABLE Hotel ADD FOREIGN KEY (Manager_ID, Hotel_ID) REFERENCES Staff(Id, Hotel_Id);
Unfortunately, you cannot use a CHECK CONSTRAINT
on the value of the Id
column. If you could, it would be possible to write something like:
ALTER TABLE Hotel ADD CONSTRAINT CHK_Hotel CHECK (Hotel_ID = Id OR Hotel_Id IS NULL);
This would verify that the Hotel_Id
column, which value come from the Staff
table, must be the same as the Id
column. However, you will get the following error message:
Check constraint 'CHK_Hotel' cannot refer to an auto-increment column.
You have to add a trigger for INSERT
and UPDATE
queries (see questions like Constant column value in MySQL table) to make that check.
The following example queries shows how the foreign keys are working:
INSERT INTO Hotel (Name) VALUES ('Some Hotel Name');
SELECT * FROM Hotel;
+----+-----------------+------------+----------+
| Id | Name | Manager_ID | Hotel_ID |
+----+-----------------+------------+----------+
| 1 | Some Hotel Name | NULL | NULL |
+----+-----------------+------------+----------+
INSERT INTO Staff (Hotel_Id, FirstName, LastName) VALUES (1, 'John', 'Doe');
SELECT * FROM Staff;
+----+----------+-----------+----------+
| Id | Hotel_Id | FirstName | LastName |
+----+----------+-----------+----------+
| 1 | 1 | John | Doe |
+----+----------+-----------+----------+
UPDATE Hotel SET Manager_Id = 1, Hotel_Id = 1 WHERE Id = 1;
SELECT * FROM Hotel;
+----+-----------------+------------+----------+
| Id | Name | Manager_ID | Hotel_ID |
+----+-----------------+------------+----------+
| 1 | Some Hotel Name | 1 | 1 |
+----+-----------------+------------+----------+
UPDATE Hotel SET Manager_Id = 1, Hotel_Id = 2 WHERE Id = 1;
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`Hotel`, CONSTRAINT `Hotel_ibfk_1` FOREIGN KEY (`Manager_ID`, `Hotel_ID`) REFERENCES `Staff` (`Id`, `Hotel_Id`))