欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > mysql多表关系与查询

mysql多表关系与查询

2024/12/1 10:48:58 来源:https://blog.csdn.net/smile_pbb/article/details/143052659  浏览:    关键词:mysql多表关系与查询

一、多表关系

1.多表操作分类

1.1 多对一

关系举例:
多对一:多名学生在一个班级里
一对多主要是靠 “外键” 实现。在 “多” 的表中建立外键,指向 "一"的主键
一对多的关系在实际生产当中使用非常常见。
一对多的核心解决方案是:如何让记录能够正确的匹配到另外表中的数据

1.2 多对多

关系举例:

一个学生可以学习多门课程。一门课程也可以被多名学生学习。
多对多主要是第三张表来维护两张表之间的关系。第三张表主要记录两张表的主键来记录对应关系。
这两个字段分别使用外键来关联两张表的主键

1.3 一对一

一对一的关系,多用于单表拆分,将一张表的基础字段放在一张表中,详情信息放在另外一张表中,以提升操作效率。
实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

1.4 区别

多对一:

​ 1.A表的一行数据只能和B表的某一行数据建立关系
​ 2.B表的一行数据可以和A表的多数据建立联系
多对多:
​ 1.A表的一行数据可以和B表的多行数据建立关系
​ 2.B表的一行数据也可以和A表的多行数据建立关系

2.多对一

在前边的 “约束” 中没有写外键约束,就是放在这里在举例。

2.1 外键概念

在一张表中指向外部表 “主键””的字段定义成为 “外键”.

2.2 外键语法

外键必须要通过语法指定才能称之为外键.
外键也可以不指定名称,系统会自动生成

[constraint 外键名] foreign key(当前表字段名) references 外部表(主键字段)

2.3 外键构成条件

外键字段必须与对应表的主键字段类型一致
外键字段本身要求是一个索引(创建外键会自动生成一个索引)

2.4 建立一(班级表)

create table class( id int primary key auto_increment, name varchar(50) not null unique 
)charset utf8;

2.5 建立多(学生表)

create table students( id int primary key auto_increment,name varchar(50) not null,c_id int comment  "指向class表的主键",foreign key(c_id) references class(id)
);

2.6 新增班级数据

INSERT INTO class VALUES(NULL,"python"),
(NULL,"C"),
(NULL,"C++"),
(NULL,"java"),
(NULL,"go");

内容如下:

mysql> select * from class;
+----+--------+
| id | name   |
+----+--------+
|  2 | C      |
|  3 | C++    |
|  5 | go     |
|  4 | java   |
|  1 | python |
+----+--------+

2.7 新增学生表数据

INSERT INTO students VALUES(NULL,"张三",1),
(NULL,"李四",2),
(NULL,"王五",1),
(NULL,"王强",2),
(NULL,"孙红",4);

结果如下:

mysql> select * from students;
+----+--------+------+
| id | name   | c_id |
+----+--------+------+
|  1 | 张三   |    1 |
|  2 | 李四   |    2 |
|  3 | 王五   |    1 |
|  4 | 王强   |    2 |
|  5 | 孙红   |    4 |
+----+--------+------+

3.多对多

3.1 创建表1

创建武林高手表

CREATE TABLE persion(id INT AUTO_INCREMENT PRIMARY KEY,NAME VARCHAR(20)
)

插入数据

INSERT INTO persion VALUES(NULL,"张无忌"),
(NULL,"周芷若"),
(NULL,"谢逊"),
(NULL,"崆峒五老"),
(NULL,"黄衫女");

内容如下:

mysql> select * from persion;
+----+--------------+
| id | NAME         |
+----+--------------+
|  1 | 张无忌       |
|  2 | 周芷若       |
|  3 | 谢逊         |
|  4 | 崆峒五老     |
|  5 | 黄衫女       |
+----+--------------+

3.2 创建表2

创建武功秘籍表

CREATE TABLE manual(id INT AUTO_INCREMENT PRIMARY KEY,NAME VARCHAR(30)
) 

插入数据

INSERT INTO manual VALUES(NULL,"九阴真经"),
(NULL,"七伤拳"),
(NULL,"乾坤大挪移");

查询数据

mysql> select * from manual;
+----+-----------------+
| id | NAME            |
+----+-----------------+
|  1 | 九阴真经          |
|  2 | 七伤拳           |
|  3 | 乾坤大挪移        |
+----+-----------------+

3.2 创建关系表

两个字段分别关联到persion表和manual表的两个主键

CREATE TABLE PersionToManual(id INT AUTO_INCREMENT PRIMARY KEY,persion_id INT,manual_id INT,FOREIGN KEY(persion_id) REFERENCES persion(id),FOREIGN KEY(manual_id) REFERENCES manual(id)
)

插入数据

INSERT INTO PersionToManual VALUES(NULL,1,2),
(NULL,1,3),
(NULL,2,1),
(NULL,3,2),
(NULL,4,2),
(NULL,5,1)

查询结果如下:

mysql> SELECT * FROM PersionToManual;
+----+------------+-----------+
| id | persion_id | manual_id |
+----+------------+-----------+
|  1 |          1 |         2 |
|  2 |          1 |         3 |
|  3 |          2 |         1 |
|  4 |          3 |         2 |
|  5 |          4 |         2 |
|  6 |          5 |         1 |
+----+------------+-----------+

4.一对一

一对一关系,多用于表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
一对一的实现主要是靠 在任意一方加入外键,关联另外一方的主键,并且设置外键唯一(UNIQUE)

二、多表查询

1.内连接

内连接的连接条件必须是 外键id = 主表主键id
内连接查询的是两张表交集的部分。
这里的查询实例使用的是上边的class表和students表,这里在students表中插入了一条没有外键id的一行数据,为了能够明显的看出效果

INSERT INTO students VALUES(NULL,"高圆圆",NULL)

1.1 隐士内连接

语法:

SELECT 字段名 FROM 表1,表2 WHERE 表1.字段 = 表2.字段

。如果不加条件,直接查询连长表,就会出现笛卡尔乘积

SELECT * FROM students,class

使用隐士内连接进行查询。

SELECT * FROM students,class WHERE students.c_id = class.id

查询结果如下:结果中没有出现笛卡尔乘积

mysql> SELECT * FROM students,class WHERE students.c_id = class.id;
+----+--------+------+----+--------+
| id | name   | c_id | id | name   |
+----+--------+------+----+--------+
|  1 | 张三   |    1 |  1 | python |
|  2 | 李四   |    2 |  2 | C      |
|  3 | 王五   |    1 |  1 | python |
|  4 | 王强   |    2 |  2 | C      |
|  5 | 孙红   |    4 |  4 | java   |
+----+--------+------+----+--------+

1.2 显示内连接

语法: 其中inner可以省略

SELECT 字段名 FROM 表1 INNER JOIN 表2 ON 表1.字段 = 表2.字段

实例:这里为两张表起了别名。

SELECT  s.name, c.name FROM students s JOIN class c ON s.c_id = c.id

查询结果如下:

+--------+--------+
| name   | name   |
+--------+--------+
| 张三   | python |
| 李四   | C      |
| 王五   | python |
| 王强   | C      |
| 孙红   | java   |
+--------+--------+

2.外连接:

2.1 左外连接:

查询左表所有数据,以及两张表交集部分.这个交集部分是针对与笛卡尔积而言的
语法:

select * from 表1 left join 表2 on 条件;

实例:

SELECT * FROM students s LEFT JOIN class c ON s.c_id = c.id

结果如下:查询出了左表所有的数据以及交集部分

+----+-----------+------+------+--------+
| id | name      | c_id | id   | name   |
+----+-----------+------+------+--------+
|  1 | 张三      |    1 |    1 | python |
|  2 | 李四      |    2 |    2 | C      |
|  3 | 王五      |    1 |    1 | python |
|  4 | 王强      |    2 |    2 | C      |
|  5 | 孙红      |    4 |    4 | java   |
|  6 | 高圆圆    | NULL | NULL | NULL   |
+----+-----------+------+------+--------+

2.2 右外连接:

查询右表所有数据,以及两张表交集部分,这个交集部分是针对与笛卡尔积而言的

select * from 表1 rigth join 表2 on 条件;

实例:查询出了右表所有数据,以及两张表交集的数据

mysql> SELECT * FROM students s RIGHT JOIN class c ON s.c_id = c.id;
+------+--------+------+----+--------+
| id   | name   | c_id | id | name   |
+------+--------+------+----+--------+
|    4 | 王强   |    2 |  2 | C      |
|    2 | 李四   |    2 |  2 | C      |
| NULL | NULL   | NULL |  3 | C++    |
| NULL | NULL   | NULL |  5 | go     |
|    5 | 孙红   |    4 |  4 | java   |
|    3 | 王五   |    1 |  1 | python |
|    1 | 张三   |    1 |  1 | python |
+------+--------+------+----+--------+

3.子查询

3.1 分类

子查询类型含义
标量子查询子查询返回结果为单个值
列子查询子查询返回结果为一列
行子查询子查询返回结果为一行
表子查询子查询返回结果为多行多列

根据位置又可以分为:

在where之后出现、from后边出现、select之后出现的子查询

3.2 标量子查询

常用的操作符号:=,<> >,>= <,<=
这里还是使用class和students表
例子: 查询学习C语言的学生有谁

SELECT * FROM students WHERE c_id = (SELECT id FROM class WHERE NAME = "C")

3.2 列子查询

常用的操作符有

操作符号含义
IN在指定的集合范围之内,多选一
NOT IN不在指定的集合范围之内
ANY子查询返回列表中,有任意一个满足即可
SOME与any等同,使用some的地方都可以使用any
ALL子查询返回列表的值都必须满足

例子:

查询学习C或者C++的学生有谁

SELECT * FROM students WHERE c_id IN(SELECT id FROM class WHERE NAME = "c" OR NAME ="c++")

3.2 行子查询

这里没有合适数据,只写一下语法

select * fromwhere (字段1,字段2) = (子查询回来的两个字段结果)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com