一篇搞定Sql联表查询

Posted HUTEROX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇搞定Sql联表查询相关的知识,希望对你有一定的参考价值。

前言

刚好最近玩mybatisplus,就顺便再整理一下有关Sql 的内容。本来是想要全部整理一下的,突然发现前面也写了一些博客关于数据库的讲的其实也比较完善,所以就不打算全部直接整理了。以下是关于Sql的相关文章。
Mariadb的基本使用(一篇涵盖基本操作)

SQL查询语句&注入实战(手注,显注)(这篇博客其实讲的更多的也是有关数据的查询,只是结合了注入)。基本上加上这篇数据库部分差不多了,后面结合事务,视图,索引什么的其实也很简单,稍微难一点的就是锁,涉及到同步并发之类的玩意,但是这个更多的是代码级别的操作,而且推荐用你的Java代码python代码去做!那么数据库部分就不多阐述了。

级联

首先先说一下啊,在实际的操作过程当中,据阿里巴巴的开发手册说禁止表的级联,所有的相关操作应该在代码里面实现逻辑级联。这个其实也是为了安全嘛,当然我也是现在才知道,我的哪个White Hole里面不知道用了多少个级联。
所谓的级联其实很简单,举个以前的老例子就明白了。学生表和班级表。
学生表里面一定有一个字段存放班级的ID,那么这个存放班级ID的字段是不是需要约束。
用这个约束来限定学生表里面存放的班级Id的字段的内容。例如:在班级表里面的ID里面没有“A”,那么显然在学生表存放班级ID的字段里面也不能出现“A”这个值!
下面我直接演示两个Sql语句.

创建学生表

create table student(id int primary key auto_increment,name varchar(128),age int)charset=utf8;

创建班级表

create table class(id int primary key auto_increment,name varchar(128))charset=utf8;

现在对学生表创建级联
创建新的字段给学生表

alter table student add class_id int; 

添加约束

alter table student add constraint fg_class_id foreign key(class_id) references class(id);

fg_class_id 约束名
删除约束用这个

alter table student drop constraint fg_class_id;

到这里基本上就好了。
以前基于这个我们可以实现表之间的关系,例如先前加了个外键那么我们就实现了经典的一对多关系,
一个班级对应多个学生,如果我再在约束里面加一个唯一约束那就是一对一。

alter table student add constraint fg_class_id foreign key(class_id) references class(id);
alter table student add constraint fg_class_id_un unique(fg_class_id );

看上去就实现了一个级联,至于多对多那就在创建一个表存放他们之间的Id嘛。
可参见这篇博客(不会Django不要紧看看这篇主要是讲逻辑关系以及在Django里面如何实现)
秒懂Django模型(数据库)关系(学习系列六)

说完了这个那就说说坏处,那其实就是数据级联了以后的删除问题,也就是数据安全性的问题。
先前我们的解决方案就是在当数据库的主表删除了之后从表的数据删干净的那么主表的数据才会删除。
当然这些还是在代码里面去做。
那么在这里的话还有一个玩意就是,删除和更新操作的级联。
这个很好理解那就是班级的ID改了,那么对应的学生的班级ID要不要改,当然这里可以直接在数据库实现,也可以通过代码,不过这里推荐代码实现 那这里也说一下。
我们只需要设置一下,在创建的约束的时候。

alter table student add constraint fg_class_id foreign key(class_id) references class(id) on delete cascade on update cascade;

慎用!默认都是空的,也就是不会有任何操作。

联表查询

这个联表查询其实就是把两张数据表的内容做个整合,其实更加形象一点那就是两张集合之间的交集并集等之间的关系,如果我们把每条查询语句的结果当作集合的话。
这里的话分为三大种,内联,左联,右联。
此外还能细分一下,看下图

这里我们主要说前面三种,因为其他的无非是在后面加点条件罢了。

这里给个口诀

1.明确需要查询的数据(字段)
2.明确需要从哪几张表里面查询
3.明确筛选条件

下面给个例子。
假设班级里面有个班级 A 它的Id是 1
现在查询A班学生的名字和年龄。

select s.name,s.age  
from student as s 
inner join class as c 
on s.class_id = c.id
where s.id=1;

左/右联表

这个其实还是很简单,但是区别其实就是前面那张图里面的区别。

select s.name,s.age c.name 
from student as s 
left join class as c 
on s.class_id = c.id
where s.id=1;

假设有位同学没有分班,也就是没有班级ID那么,此时我们会发现有个c.name的值为空
也就是这样

那么右联也是

其实都是很简单的玩意,但是很重要!

多表联查

这个还是一样的,我们假设现在还有一个表

create table grade(id int primary key auto_increment 
grade float,
student_id int,
foreign key(student_id) references student(id) )charset = utf8;

现在我还需要查询出学生姓名,年龄,成绩在A班里面

select name,age,grade
from student as s inner join
class as c on s.class_id = c.id
inner join grade as g
where g.student_id = s.id and c.id=1;

看到了吗,从左到右两两查询的结果为一个左集合

以上是关于一篇搞定Sql联表查询的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis-Plus 不支持联表?一个依赖轻松搞定,非常牛逼!

SQL 一对多联表查询最大值

一篇搞定SQL语句

SQL联表查询

mysql 联表查询 巨慢

来了,MyBatisPlus的join联表查询