← [ BACK_TO_NOTES ]

多对多关系与连接表

多对多关系通过连接表把 N:N 拆成两个 1:N,并允许把角色、状态、时间等关系属性存到关系本身。

#concept #growing #backend #database #sql

[!info] related notes

多对多关系与连接表

一句话定义

多对多(N:M)表示一个 A 可以关联多个 B,同时一个 B 也可以关联多个 A;在关系数据库中通常通过第三张连接表实现。

核心模型

Student 1 ─── N Enrollment N ─── 1 Course

因此数据库里的 N:M 实际被拆成两个 1:N。

CREATE TABLE enrollments (
  student_id BIGINT NOT NULL REFERENCES students(id),
  course_id  BIGINT NOT NULL REFERENCES courses(id),
  UNIQUE (student_id, course_id)
);

为什么需要连接表

把多个 ID 塞进 students.course_ids 或 courses.student_ids 会让引用完整性、索引、JOIN 和约束都变得困难。连接表让“一条关系”本身成为一行,可以被查询和约束。

关系本身也可以有属性

如果选课还需要记录:

enrolled_at
grade
status

这些字段描述的是“某个 Student 与某门 Course 的关系”,应放在 enrollments,而不是 students 或 courses。

同理:

  • Membership.role
  • ReadingList.read
  • OrderItem.quantity

一旦连接关系拥有自己的状态、生命周期或行为,它往往已经是一个真正的领域实体,而不只是技术胶水。

唯一性与主键

常见两种设计:

  1. (student_id, course_id) 直接作为复合主键;
  2. 使用独立 id 主键,同时增加 UNIQUE (student_id, course_id)。

选择取决于关系是否需要被其他表单独引用、ORM 使用习惯和领域身份需求。

边界与常见误解

  • N:M 是关系的基数,不等于必须使用某个 ORM 的 belongsToMany API。
  • 连接表上的属性属于关系;课程自身的 credits 仍应放 courses。
  • 如果同一对实体允许多次建立有意义的关系(如同一学生可多学期重修同一课程),UNIQUE(student_id, course_id) 可能过强,应把 term 等维度纳入唯一键。
创建于 2026/9/14 更新于 2026/9/14
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本