复合主键和唯一键作为外键

时间:2011-12-26 06:03:18

标签: mysql database foreign-keys normalization composite

好的就是这种情况。

  • 一所大学有一个以上的教师。
  • 每个教师都有不止一个部门。

我不希望任何重复的教师或部门。所以我在下面定义了三个表。

CREATE TABLE university (
    id INT PRIMARY KEY AUTO_INCREMENT,
    long_name VARCHAR(255) UNIQUE NOT NULL,
    name VARCHAR(255) NOT NULL,
    country VARCHAR(45) NOT NULL,
) Engine=InnoDB;

CREATE TABLE school_faculty (
    id INT UNIQUE NOT NULL AUTO_INCREMENT,
    name VARCHAR(45),
    universityID INT,
    PRIMARY KEY (name, universityID),
    FOREIGN KEY (universityID) REFERENCES university (id)
) Engine=InnoDB;

CREATE TABLE department (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(45) NOT NULL,
    schoolfacultyID INT NOT NULL,
    FOREIGN KEY (schoolfacultyID)
        REFERENCES school_faculty (id)
) Engine=InnoDB;

请告诉我它是否错误或是否有更好的方法。我正在努力,有点无助。

2 个答案:

答案 0 :(得分:0)

看起来不错。

您可以通过拥有一个只有falculty / department名称的表格并将您的department / falculty表格转换为(universityID,facultyNameID)来使事情更正常化。但这种正常化水平可能有点过分。虽然很可能在所有大学中都有一个物理或篮子编织教师,但是通过在表格中保留“物理”这个词的多个副本而使用的少量额外字节不会破坏银行。

同样适用于部门,同样“也许不是问题”。

答案 1 :(得分:-1)

school_faculty表外,你没事。最好使用以下模式:

CREATE TABLE school_faculty (
    id PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(45),
    universityID INT,
    UNIQUE (name, universityID),
    FOREIGN KEY (universityID) REFERENCES university (id)
) Engine=InnoDB;

最好使用整数列作为PK而不是复合键。在InnoDB表中,PK是clustered index,因此使用PK的最小数据类型意味着MySQL可以从每次扫描的索引中读取更多数据。在大多数情况下,主键自动递增更好,这样可以轻松订购(它们基本上已经订购)。

此外,辅助(非群集)索引存储来自PK的数据。使用较小的类型意味着二级索引占用较少的空间。任何使用二级索引的查询都必须使用PK来访问实际的行数据,这样才能从通过PK改善访问时间的任何事情中受益。

您还应该在部门(name,schoolfacultyID)上添加一个唯一键,以防止给定教师中的重复部门。

希望它有所帮助。