2

这个问题适用于不同的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)
);

tableMale和tableFemale之所以分开是因为它们是由不同的 sql 帐户维护的。


现在的问题是Association Class

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

所以我的问题是:

  • 如何设置StudentIDMaleFemale. 我在网上找不到那个。
  • 如何强制执行Foreign Key关联类表的值列来自两个表的约束:MaleFemale

建议也被接受。

谢谢你

4

3 回答 3

2

这就是属性拆分不好的原因——它开始以奇怪的方式“感染”其他表。

你可以有:

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

据我所知,由于 MySQL 不支持CHECK约束,因此您还必须创建一个触发器,以确保只有一个,并且恰好一个,MaleStudentIDFemaleStudentIDis NOT NULL

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


对于 SQL Server,您有一个检查约束:

ALTER 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)
)
于 2013-01-22T07:28:44.630 回答
1

你可以:

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

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

拉吉

于 2013-01-22T06:59:25.877 回答
1

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

另一种解决方案是将你的 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)
)
于 2013-01-22T07:21:09.873 回答