首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RDB中的子关系

RDB中的子关系
EN

Stack Overflow用户
提问于 2015-10-25 10:19:05
回答 1查看 87关注 0票数 1

在典型的RDB中,我可以描述与外键的关系。然而,我不知道如何能够有效地描述一个群体内部的关系。我知道这很难理解,所以让我来描述一下这个场景。

我想做一个梯度书服务,在那里教师可以注册和创建课程,学生可以注册和注册课程。

代码语言:javascript
复制
CREATE TABLE teachers (
   id BIGSERIAL PRIMARY KEY,
   name VARCHAR(255),
   ...
)

CREATE TABLE students (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(255),
  ...
)

CREATE TABLE classes (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(255),
  teacher_id BIGINT REFERENCES teachers(id)
)

CREATE TABLE enrollments (
  student_id BIGINT REFERENCES students(id),
  class_id BIGINT REFERENCES classes(id),
  PRIMARY KEY (student_id, class_id)
)

在每堂课上,老师都可以做作业,每个学生都会得到作业的分数。

代码语言:javascript
复制
CREATE TABLE assignments (
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(255),
  class_id BIGINT REFERENCES class(id)
  ...
)

现在,我要描述一个分数属于一个学生,和一个外键作业。

代码语言:javascript
复制
CREATE TABLE scores (
  id BIGSERIAL PRIMARY KEY,
  score INT,
  student_id BIGINT REFERENCES student(id),
  assignment_id BIGINT REFERENCES assignments(id)
)

然而,没有什么能阻止我为一个没有参加这门课的学生创造一个分数。换句话说,分数必须附有相应的注册(相同的学生身份)。我之所以说这是子关系,是因为分数的关系应该在一个类中局部地限定范围。

我如何在RDB中强制执行这样的限制?

更新

根据@Joel的建议,这就是我想出的。

代码语言:javascript
复制
CREATE TABLE enrollments (
  class_id BIGINT REFERENCES classes(id),
  student_id BIGINT REFERENCES students(id),
  PRIMARY KEY (class_id, student_id)
);

CREATE TABLE assignments (
  id BIGSERIAL,
  class_id BIGINT REFERENCES classes(id),
  name VARCHAR(255) NOT NULL,
  max_possible_score INT NOT NULL,
  PRIMARY KEY (id, class_id)
);

CREATE TABLE scores (
  class_id BIGINT,
  student_id BIGINT,
  assignment_id BIGINT,
  PRIMARY KEY (assignment_id, class_id, student_id),
  FOREIGN KEY (class_id, student_id) REFERENCES enrollments(class_id, student_id),
  FOREIGN KEY (assignment_id, class_id) REFERENCES assignments(id, class_id)
);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-25 12:46:48

如果要确保学生在未注册的班级的作业中不能获得SCORE,则有两个选项:

  1. 使用应用逻辑
  2. 使用声明引用完整性

有些人可能会说,您现在的数据模型工作得很好,但是它需要一些应用程序逻辑来对创建SCORE进行理智检查,以确保学生应该有这个分数。

如果要确保不使用应用程序逻辑就不会发生这种情况,则必须更改数据模型。当前的数据模型如下所示:

您可以将数据模型改为如下所示:

请注意以下事项:

  • Assignment部分是由CLASS的外键识别的。这将类ID向下拉到赋值,以便由SCORE在其主键中依次引用它。
  • SCOREENROLLMENT直接相关,而不是与STUDENT直接相关。这是有意义的,因为注册是属于一个班级的学生的记录,所以它更紧密地模拟了你所关心的强加的商业规则。
  • SCORE的主键由ENROLLMENT (包括学生ID)和ASSIGNMENT (包括类ID)的外键组成。
  • 这意味着SCORE的主要关键是课堂、作业和学生的结合。

如果您确保在SCORE表中只保留了一个类ID副本,那么学生就不可能在作业中获得分数,除非该学生也注册了分配该作业的班级。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33328539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档