SQL:作为另一个外键的子项的外键

时间:2012-08-21 08:38:40

标签: sql foreign-keys

我想问一下我遇到的一个特定问题。

例如,我有一个Student表,其中包含SchoolIDClassID,这两个表都是SchoolClassroom的外键分别表。 Class表有一个SchoolID列,它是School表的外键。

有什么方法可以确保ClassID表格中的StudentSchoolID的孩子,或者我必须删除SchoolID才能确定ClassID是为了防止出现任何可能的差异?

3 个答案:

答案 0 :(得分:1)

是的,从技术上讲,如果Class已经有Student.SchoolId,那么您应该删除SchoolId外键,因为这已经定义了StudentSchool之间的关系。

也就是说,有一些常见的“例外”,例如:

  1. 如果StudentSchool之间的关系可能与ClassSchool之间的关系有所不同(例如,如果学生去学校X时'他/她的主要学校',但随后还在Z学校参加额外的Y级壁画。 (实际上,这可能会突出显示建模错误,即Student:Class实际上可能是多对多的关系)

  2. 出于性能原因,有时(有点不情愿)选择将父母的外键添加到子节点以避免需要加入父节点。但正如您所说,这可能导致完整性问题。

答案 1 :(得分:1)

是的,您可以通过在Classes表的外键引用中包含多个列来强制执行它:

create table Schools (
    SchoolID int not null primary key,
    Name varchar(30) not null unique
)
go
create table Classes (
    ClassID int not null primary key,
    SchoolID int not null foreign key references Schools (SchoolID),
    Name varchar(30) not null,
    constraint UQ_Class_Schools UNIQUE (ClassID,SchoolID),
    constraint UQ_Class_Names UNIQUE (SchoolID,Name)
)
go
create table Students (
    StudentID int not null primary key,
    SchoolID int not null foreign key references Schools (SchoolID),
    ClassID int not null,
    Name varchar(95) not null,
    constraint FK_Student_Classes FOREIGN KEY (ClassID,SchoolID) references Classes (ClassID,SchoolID)
)

根据品味,您可能还决定在两个表的ClassID列中声明外键

答案 2 :(得分:0)

学生表应该引用Class。

create table Student (
  ...
  SchoolID integer not null,
  ClassID integer not null,
  foreign key (SchoolID, ClassID) references Class (SchoolID, ClassID),
  ...
);

反过来,Class表应该引用School。