一、表之间的关系类型
1.1 一对一
定义:A表中的一行数据对应B表中的一行数据,且B表中的一行数据也对应着A表中的一行数据。
比如:人员表和驾照表,每一个人只有一个驾照,每个驾照也只对应一个人。
1.2 一对多
定义:A表中的一行数据可对应B表中的多行数据,但B表中的一行数据仅能对应A表中的一行数据。这是数据库中最常见的关系类型。
比如:学生表和班级表,每个班级里有很多学生,但是每个学生只有一个班级。
1.3 多对多
定义:A表中的一行数据可对应B表中的多行数据,反之亦然。标与表之间的关联需要通过中间表(关联表)实现。
比如:比如学生表和课程表,每个学生要上多门课程,每门课程也有很多学生要参加。
二、外键与关系体现
2.1 什么是外键
外键(Foreign Key)是关系型数据库中的一个核心概念,它是用于建立两个表之间的关联关系的,通常情况下,一张表的主键会作为另一张表的外键,例如,学生表包含学生id、姓名等字段,班级表包含班级id、班级名称等字段,在设计数据库时,我们可以通过在学生表中添加班级id作为外键,建立与班级表的关联关系。
2.2 外键的语法
2.2.1 一对一和一对多
在一对一和一对多时,我们可以在创建表时在语句最后声明外键,具体语法如下:
sql
-- 其中,"外键名"是为这个关系命名,是自定义的,本表外键列名就是在本表中外键的名字,
-- 之后就是这个字段作为主键时的那张表名 + (主表时它的名字)
CONSTRAINT 外键名 FOREIGN KEY (本表外键列名) REFERENCES 主表名(主表主键列名)
2.2.2 多对多
多对多的表关系之间会存在重复的情况,比如学生表和课程表,一个学生有多门课程,我们该选那门作为外键关联呢?反之也是如此。
虽然这些是重复的,但是他们的关系组合在一起就是独特的一个字段了,所以这时我们就需要再建一个表,在这个表中存放学生id和课程id,使他们在第三张表中一一对应,这样也可以显现两张表之间的关系了。
1)我们可以在关系表中定义一个字段id作为这张表的主键,比如:
sql
CREATE TABLE t_s_c(
id INT PRIMARY KEY AUTO_INCREMENT,
sid INT,
cid INT,
CONSTRAINT fk_student_id GOREIGN KEY (sid) REFERENCES t_student(id),
CONSTRAINT fk_course_id FOREIGN KEY (cid) REFERENCES t_course(id)
);
2)但是这样写我们会发现,这张表中出现了第三个字段,也就是关系表的id,但是这是一张关系表,如果我们只想要他连接的两张表的id出现在这里,进行一一对应该怎么办呢?但是又不能没有主键,所以我们就有第二种写法,我们可以定义一个联合主键。
sql
CREATE TABLE t_s_c(
sid INT,
cid INT,
CONSTRAINT fk_student_id GOREIGN KEY (sid) REFERENCES t_student(id),
CONSTRAINT fk_course_id FOREIGN KEY (cid) REFERENCES t_course(id),
PRIMARY KEY(sid,cid) --联合主键
);
2.3 不同关系中外键的设置
不同的关系中,外键该如何去建,一般建在哪,需要初学者去思考一下。如果一对多时,外键建在"一"的一方,那么肯定会出现咱们上边说的重复的情况,所以具体的建议如下:
- 一对一关系:外键可以存在于任意一方,具体视实际需求而定。
- 一对多关系:外键设置在"多"的一方。
- 多对多关系:外键不直接存储在实体表中,而是建在第三张表(关系表)中。
2.4 表的创建和删除
表的创建和删除,我们需要考虑到这个表的建立,里边的内容完不完整,会不会影响到其他表。
下面是创建和删除的建议:
- 创建:建议先创建没有外键的表。
- 删除:建议先删除有外键的表。
三、表连接方式详解
表连接就是将不同的表通过外键的方式连接在一起形成一张大表,然后通过查询展示出来,其本身并不会对表内数据产生影响。
3.1 内连接
内连接的特点:只显示满足连接条件的数据,不满足条件的不显示。比如学生表和班级表:
学生表:
|------------|------|----------|
| student_id | name | class_id |
| 1001 | 张三 | 201 |
| 1002 | 李四 | 202 |
| 1003 | 王五 | null |
班级表:
|----------|------------|
| class_id | class_name |
| 201 | 一班 |
| 202 | 二班 |
| 203 | 三班 |
我们在执行内连接时,会将这两张表连接,但是内连接只会显示有一一对应关系的数据,所以'王五'没有班级id,同样203班也没有学生和它对应,所以连接后只会显示:
|------------|------|----------|------------|
| student_id | name | class_id | class_name |
| 1001 | 张三 | 201 | 一班 |
| 1002 | 李四 | 202 | 二班 |
这就是内连接的特点。
3.1.1 隐式内连接
也就是隐藏了内连接的语法,语法如下:
sql
SELECT *
FROM student s, class c,
WHERE s.class_id = c.class_id;
3.1.2 显式内连接
显式连接,语法如下:
sql
SELECT *
FROM student s
INNER JOIN class c
ON s.class_id = c.class_id;
3.2 外连接
外连接和内连接不同,他是以其中的一个表为依据,该表中的所有数据都会显示,即使对应的外键为空,但是另一个表中如果没有和这个表对应的数据,还是不会显示。说白了就像是通过一个表去查找另一个表的数据,查到了就写出来,没查到就空着这种逻辑。
如果以学生表为依据的话,那么查询的结果如下:
|------------|------|----------|------------|
| student_id | name | class_id | class_name |
| 1001 | 张三 | 201 | 一班 |
| 1002 | 李四 | 202 | 二班 |
| 1003 | 王五 | null | null |
3.2.1 左外连接
以左表为主表,左表所有数据均显示,右表满足连接条件的显示,不满足的不显示,语法如下:
sql
SELECT 字段...
FROM 表1
LEFT [OUTER] JOIN 表2
ON 连接条件
3.2.2 右外连接
以右表为主表,右表所有数据均显示,左表满足连接条件的显示,不满足的不显示,语法如下:
sql
SELECT 字段...
FROM 表1
RIGHT [OUTER] JOIN 表2
ON 连接条件
3.3 自连接
自连接,就是两张参与连接的表其实是同一张表,其实可以理解为把这个表拷贝了一份,把它当作两张不同的表去看待,一般会应用在查找这张表中某个数据的一些信息,比如:
- 查找同一产品在不同时间的价格变化
- 比较同一学生在不同学期的成绩变化
同时在使用时,我们需要给from和join的表都起别名来区分,具体的使用根据情况使用内连接或外连接。
3.4 多表连接
上面我们说了,两张表的连接结果可以当作是一张大表来看待,既然是一张表,那么他就可以和其他表进行连接,其实和子查询有点相似,也就是将第三张表和连接的大表作为表1和表2,去根据情景不同,使用内连接和外连接,然后如此如此可以一直嵌套下去。