SQL-多对多关系

一、场景背景:多对多关系的业务逻辑

在实际业务中,"学生" 和 "课程" 存在典型的多对多关系

  • 一个学生可以选择多门课程(1 个学生 → N 门课程);
  • 一门课程可以被多个学生选择(1 门课程 → N 个学生)。

这种关系无法直接通过两个表的字段关联实现(会导致数据冗余或关联混乱),因此需要引入中间表 来维护两者的关联关系。上述代码中,student(学生表)和course(课程表)是两个主体表,student_course(学生 - 课程中间表)是关联表。

二、表结构设计与核心语法解析

1. 学生表(student

sql

sql 复制代码
create table student(
    id int auto_increment primary key comment '主键ID',
    name varchar(10) not null unique comment '名字',
    no varchar(10) comment '学号'  -- 注:原代码注释有误,应为"学号"
)comment '学生表';
  • 核心字段解析
    • id:整数类型(int),作为主键(primary key),且设置auto_increment(自增)。
      • 主键(primary key):唯一标识表中的每条记录,确保记录不重复,且加速查询(主键会自动创建索引)。
      • 自增(auto_increment):插入数据时无需手动指定id值,MySQL 会自动生成唯一的递增数值(默认从 1 开始),简化插入操作。
    • name:字符串类型(varchar(10),最长 10 个字符),设置not null(非空,必须填写)和unique(唯一,不允许重复的学生姓名)。
    • no:字符串类型,注释为 "学号"(原代码注释笔误),未设置非空约束,允许为空。
  • comment:为表和字段添加注释,提高代码可读性(可通过show full columns from 表名;查看)。
2. 课程表(course

sql

sql 复制代码
create table course(
    id int auto_increment primary key comment '主键ID',
    name varchar(10) comment '课程名字'
)comment '课程表';
  • 结构与student表类似,核心字段为id(自增主键)和name(课程名称,未设置唯一约束,允许同名课程,具体根据业务需求调整)。
3. 中间表(student_course

中间表是多对多关系的核心,用于记录学生和课程的关联关系:

sql

sql 复制代码
create table student_course(
    id int auto_increment primary key comment '主键',
    student_id int not null comment '学生ID',
    course_id int not null comment '课程ID',
    constraint fk_student_id foreign key (student_id) references student(id),
    constraint fk_course_id foreign key (course_id) references course(id)
)comment '学生课程中间表';
  • 核心设计逻辑

    • 包含两个外键字段:student_id(关联学生表的id)和course_id(关联课程表的id),通过这两个字段建立学生和课程的关联。
    • 自身主键id:中间表也可以用student_idcourse_id作为联合主键primary key(student_id, course_id)),但此处用自增id作为主键,更便于后续对关联记录的单独操作(如删除某条选课记录)。
  • 外键约束(foreign key)详解:外键是维护数据完整性的核心约束,用于确保关联字段的值必须在被关联表中存在。

    • constraint fk_student_id:为外键约束命名(便于后续删除或修改约束)。
    • foreign key (student_id) references student(id):表示student_id的值必须是student表中已存在的id(否则插入 / 更新会失败)。
    • 同理,course_id必须是course表中已存在的id
    • 作用:避免 "无效关联"(如关联一个不存在的学生或课程),保证数据一致性。

三、数据插入(insert)操作解析

通过insert语句向表中插入数据,验证多对多关系的实际存储:

1. 向学生表插入数据

sql

sql 复制代码
insert into student values (null, '带一丝','2000100109'),
                           (null, '谢谢从','2000100107'),
                           (null, '带二四','2000100105'),
                           (null, '带三丝','2000100101');
  • values后的null对应自增主键id,MySQL 会自动生成1、2、3、4(按插入顺序)。
  • 插入后学生表数据:
id name no
1 带一丝 2000100109
2 谢谢从 2000100107
3 带二四 2000100105
4 带三丝 2000100101
2. 向课程表插入数据

sql

复制代码
insert into course values (null, 'mysql'),(null,'PHP'),(null, 'Java'),(null, 'Hadoop');
  • 课程表id自动生成1、2、3、4,对应课程名:
id name
1 mysql
2 PHP
3 Java
4 Hadoop
3. 向中间表插入关联数据

sql

sql 复制代码
insert into student_course values (null,1,1 ),(null,1,2),
                                  (null, 2,2),(null, 2,3),
                                  (null,3,4);
  • 每条记录代表 "某个学生选了某门课":

    • (null,1,1):学生 1(带一丝)选了课程 1(mysql);
    • (null,1,2):学生 1 选了课程 2(PHP);
    • (null,2,2):学生 2(谢谢从)选了课程 2(PHP);
    • (null,2,3):学生 2 选了课程 3(Java);
    • (null,3,4):学生 3(带二四)选了课程 4(Hadoop)。
  • 插入后中间表数据:

id student_id course_id
1 1 1
2 1 2
3 2 2
4 2 3
5 3 4
  • 注意:学生 4(带三丝)未选课,课程 1(mysql)仅学生 1 选,课程 4(Hadoop)仅学生 3 选,体现了多对多关系的灵活性。

四、多对多关系的查询场景(延伸)

通过中间表可以查询多对多关系的具体数据,例如:

  1. 查询 "带一丝" 选了哪些课程:

sql

sql 复制代码
select s.name, c.name 
from student s
join student_course sc on s.id = sc.student_id
join course c on sc.course_id = c.id
where s.name = '带一丝';

结果:

name name
带一丝 mysql
带一丝 PHP
  1. 查询 "PHP" 课程被哪些学生选了:

sql

sql 复制代码
select c.name, s.name 
from course c
join student_course sc on c.id = sc.course_id
join student s on sc.student_id = s.id
where c.name = 'PHP';

结果:

name name
PHP 带一丝
PHP 谢谢从

五、总结

  1. 多对多关系设计核心:通过 "主体表 A + 主体表 B + 中间表(含 A 和 B 的外键)" 实现,避免数据冗余。
  2. 约束的作用
    • 主键(primary key):唯一标识记录,加速查询。
    • 自增(auto_increment):简化主键值的生成。
    • 非空(not null)和唯一(unique):保证字段数据的有效性。
    • 外键(foreign key):维护关联数据的一致性,防止无效关联。
  3. 中间表的意义:作为多对多关系的 "桥梁",存储两个主体表的关联记录,是查询关联数据的核心。

通过上述设计,MySQL 能高效维护学生与课程的多对多关系,并支持灵活的关联查询。

相关推荐
cyy2983 小时前
android 屏幕适配
android
liliangcsdn4 小时前
LLM时代基于unstructured解析非结构化pdf
linux·服务器·数据分析
在云上(oncloudai)4 小时前
深入解析 Amazon Athena:云上高效数据分析的关键引擎
数据挖掘·数据分析
Digitally4 小时前
如何通过 5 种有效方法同步 Android 和 Mac
android·macos
哲Zheᗜe༘5 小时前
了解学习MySQL数据库基础
数据库·学习·mysql
咋吃都不胖lyh5 小时前
MySQL 多表查询中,联合查询(UNION) 和子查询
mysql·数据分析
B站_计算机毕业设计之家6 小时前
机器学习实战项目:Python+Flask 汽车销量分析可视化系统(requests爬车主之家+可视化 源码+文档)✅
人工智能·python·机器学习·数据分析·flask·汽车·可视化
行墨6 小时前
Jetpack Compose 深入浅出(二)——基础组件Text
android
先鱼鲨生6 小时前
【MySQL】认识数据库以及MySQL安装
数据库·mysql