强制唯一性并从多个表定义外键约束

时间:2013-01-22 06:48:37

标签: mysql sql-server database-design foreign-keys unique-constraint

此问题适用于不同的RDBMSMySQLSQL Server

我整晚都在寻找这个,我在网上找不到它。我的问题是唯一性外键。请考虑以下架构:

CREATE TABLE Male
(
    StudentID INT,
    FirstName VARCHAR(20) NOT NULL,
    MiddleName VARCHAR(20) NOT NULL,
    LastName VARCHAR(20) NOT NULL,
    -- other columns ...
    CONSTRAINT male_PK PRIMARY KEY (StudentID),
    CONSTRAINT male_UQ UNIQUE (FirstName, MiddleName, LastName)
);

CREATE TABLE Female
(
    StudentID INT,
    FirstName VARCHAR(20) NOT NULL,
    MiddleName VARCHAR(20) NOT NULL,
    LastName VARCHAR(20) NOT NULL,
    -- other columns ...
    CONSTRAINT Female_PK PRIMARY KEY (StudentID),
    CONSTRAINT Female_UQ UNIQUE (FirstName, MiddleName, LastName)
);

CREATE TABLE ClassList
(
    ClassID INT,
    Name VARCHAR(30),
    ClassYear INT,
    -- other columns ...
    CONSTRAINT ClassList_PK PRIMARY KEY (ClassID),
    CONSTRAINT ClassList_UQ UNIQUE (Name, ClassYear)
);

MaleFemale分开的原因是因为它们由不同的sql帐户维护。


现在的问题是关联类

CREATE Student_Class
(
    SudentID INT,
    ClassID INT,
    CONSTRAINT tb_UQ UNIQUE (StudentID, ClassID)
)

所以我的问题是:

  • 如何设置StudentIDMale两个表中Female的唯一性。我在网上找不到。
  • 如何强制执行Foreign Key约束,其中关联类表的值列来自两个表:MaleFemale

建议也被接受。

谢谢

3 个答案:

答案 0 :(得分:2)

这就是为什么属性拆分很糟糕 - 它以奇怪的方式开始“感染”其他表。

你可以:

CREATE Student_Class
(
    MaleStudentID INT NULL,
    FemaleStudentID INT NULL,
    ClassID INT NOT NULL,
    CONSTRAINT tb_UQ UNIQUE (MaleStudentID, FemaleStudentID, ClassID)
)

由于MySQL,据我所知,不支持CHECK约束,因此您还必须创建一个触发器,以确保MaleStudentIDFemaleStudentID只有一个,而且只有一个NOT NULLALTER TABLE Student_Class ADD CONSTRAINT CK_Students_Nullability CHECK ( (MaleStudentID is null and FemaleStudentID is not null) or (MaleStudentID is not null and FemaleStudentID is null) )

您现在可以以明显的方式应用外键约束。


对于SQL Server,具有检查约束:

{{1}}

答案 1 :(得分:1)

你可以:

设置StudentID的范围以识别男/女。例如,男性为10000至19999,女性为20000至29999

或者,您可以在两个表中添加冗余列“Sex”,其中M代表男性,F代表女性,并将其作为参考的一部分

拉​​吉

答案 2 :(得分:1)

我认为让用户权限决定你的架构并不是一个好主意,但如果你必须这样做,我认为HerpaMoTeH提到的想法很好。第三个表,其中包含id,gender和id,用作性别特定表和student_class中的FK。

另一个解决方案是将student_class表拆分为两个: male_student_class和female_student_class

或者,您可以在单个学生表上为CRUD操作创建2组存储过程(男性和女性)。然后,您将拒绝为用户提供实际表的权限,但允许他们访问适当的存储过程集。您的架构将简化为:

CREATE TABLE Student
(
    StudentID INT,
    GenderId INT,
    FirstName VARCHAR(20) NOT NULL,
    MiddleName VARCHAR(20) NOT NULL,
    LastName VARCHAR(20) NOT NULL,
    -- other columns ...

);


CREATE Student_Class
(
   SudentID INT,
   ClassID INT,
  CONSTRAINT tb_UQ UNIQUE (StudentID, ClassID)
)