外键限制

时间:2020-11-07 22:41:38

标签: mysql mysql-workbench

我有两个表,分别是主键为Hotel_ID的酒店和主键为Staff_ID的员工。 酒店表还具有另一列,Manager_ID引用了Staff_ID的Staff。 员工表使用其列H_ID引用Hotel_ID来指示员工在哪家酒店工作。

我一直在试图找出是否有可能限制Manager_ID的允许值,以便仅可以将同一家酒店的工作人员任命为经理。

我知道这里有一个交叉引用,但我的理解是这应该不是问题。有人可以告诉我如何将其合并到Hotel表的create语句中吗?

2 个答案:

答案 0 :(得分:0)

您可以在role表中创建标志或staff列,以指示此人是经理还是在酒店中扮演特定角色。您将不再需要Manager_Id表中的hotel列。这些表可能看起来像这样:

Hotel
 - Id
 - Name

Staff
 - Id
 - Hotel_Id
 - IsManager
 - Firstname
 - Lastname

添加新内容时,可以设置IsManager标志,以表明此人是酒店的经理,由Hotel_Id列中的ID标识。

答案 1 :(得分:0)

您可以添加多列外键,以不仅选择人员ID,还可以选择hotel_id表中分配的hotel。这将导致看起来很奇怪的表结构,如下所示:

Hotel
 - Id
 - Name
 - Manager_Id
 - Hotel_Id

Staff
 - Id
 - Hotel_Id
 - IsManager
 - Firstname
 - Lastname

这看起来特别奇怪,因为您在Hotel表中有两次相同的ID。为了使其正常工作,当使用Id列时,您必须添加触发器以验证Hotel_IdHotel_Id的值是否相同。并且由于您有某种圆形参考(Staff通过Hotel引用了Hotel_Id表,Hotel通过Staff引用了Manager_Id表)您必须运行ALTER TABLE语句以添加其他列Manager_IdHotel_Id。查询可能看起来像这样:

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)
);

第二个索引用于Hotel表中的外键:

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);

不幸的是,您不能在CHECK CONSTRAINT列的值上使用Id。如果可以的话,可以编写如下内容:

ALTER TABLE Hotel ADD CONSTRAINT CHK_Hotel CHECK (Hotel_ID = Id OR Hotel_Id IS NULL);

这将验证来自Hotel_Id表的Staff列必须与Id列相同。但是,您将收到以下错误消息:

检查约束“ CHK_Hotel”无法引用自动递增列。

您必须为INSERTUPDATE查询添加触发器(请参阅类似Constant column value in MySQL table的问题)以进行检查。

以下示例查询显示了外键的工作方式:

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`))
相关问题