文章目录
MySQL表的增删改查(进阶)
【本节目标】
- 数据库约束
- 表的关系
- 新增
- 删除
- 修改
- 查询
1.数据库约束
约束:约束就是数据库针对数据进行一系列的校验,如果发现插入的数据不符合约束中描述的校验规则,就会插入失败,约束是为了更好的保证数据的正确性。
1.1约束的类型
- NOT NULL - 指示某列不能存储 NULL 值。
- UNIQUE - 保证某列的每行必须有唯一的值。
- DEFAULT - 规定没有给列赋值时的默认值。
- PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。(相当于每个人都有的身份证号码,就是你的主键)
- FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性,即当两个表之间存在一定的关联关系的时候,通过FOREIGN KEY建立二者之间的联系(所以FOREIGN KEY涉及到两张表,难度增大)。
- CHECK - 保证列中的值符合指定的条件。对于MySQL数据库,对CHECK子句进行分析,但是MySQL数据库最终是会忽略CHECK子句的。
1.2 not null约束
创建表时,可以指定某列不为空
create table student1(
id int not null,
name varchar(20),
score decimal(3,1)
);
a)向指定列不为空的列中插入null,会提示报错
insert into student1 values(null,'孙悟空',99);
1.3 unique 唯一约束
unique :表示该列的所有行的数据是不能重复的。
a)测试unique
insert into student1 values(1,'孙悟空',88); -- true
insert into student1 values(2,'猪八戒',59); -- true
insert into student1 values(1,'沙和尚',79); -- error id列的所有行的数据是不能重复的.
b)如果既不能为空又不能重复,可以直接写unique not null,它相当于是primary key
drop table student1;
create table student1(id int unique not null,name varchar(20),score decimal(3,1));
1.4 default 默认值约束
default :当插的记录中没有针对这一列进行操作时,就给列执行默认值。
如果没有指定这一列该怎么插,就会自动填充默认值。
1.5 primary key 主键约束
primary key 相当于 not null 和unique的结合。
验证:
一般建议创建每张表的时候,最好都给这个表指定一个主键。
如何保证主键不重复呢?可以使用自增主auto_increment
人工保证不太靠谱,可以借助数据库自动来生成。MySQL里面自带了有一个auto_increment这样一个选项,通过这个选项可以让主键变成一个自增式的主键,往上自动去新增,就不会导致主键重复。
验证auto_increment -- 自增的特点是: -- 如果表中没有任何记录,自增从1开始 -- 如果表中已经有记录了,自增从上一条记录往下自增。 insert into student1 values(null,'曹操'); -- 此时这里的null就不是说真的插入null了,而是让数据库自动生成这个值,所以不会与id指定为not null 矛盾。
【注意】:如果把中间的某个数据删了之后,再插入新的数据,刚才删掉的自增主键的值不会被重复利用。
【注意】如果是int 类型的自增主键,有效范围就是-21亿 ~ +21亿,如果数据超出这个范围,再继续自增,就会出现溢出的情况。
1.6 foreign key 外键约束
foreign key 外键:描述两张表之间的关联关系。
给班级表插入数据
给学生表插入数据
外键引入
加上外键之后表的创建方式
create table class (
id int primary key auto_increment,
name varchar(20)
);
create table student(
id int primary key auto_increment,
name varchar(20),
classId int,foreign key(classId) references class(id)
);
使用外键约束需要指定三方面信息
验证
使用外键,会对插入操作的效率产生一定的影响。
外键约束也会影响表的删除,如下图:
1.7 CHECK 约束(了解)
MySQL使用时不报错,但忽略该约束:
create table test_user (
id int,
name varchar(20),
sex varchar(1), check (sex ='男' or sex='女')
);
2.表的设计
表的设计很宽泛,需要经验老道的人才能真正融入,这里先简单介绍一点基础方面的知识和数据库表设计时所涉及到的关系。
三大范式
2.1 一对一关系
2.2 一对多关系
2.3 多对多关系
多对多这个关系很复杂,需要引入中间表来解决这个问题。
例如:描述每个同学每个科目的考试成绩。
-- 创建学生表
create table student(id int primary key auto_increment,name varchar(20));
-- 创建课程表
create table course(id int primary key auto_increment,name varchar(20));
-- 向学生表插入数据
insert into student values(null,'甲'),(null,'乙'),(null,'丙'),(null,'丁');
-- 向课程表插入数据
insert into course values(null,'语文'),(null,'数学'),(null,'英语'),(null,'物理'),(null,'化学');
-- 创建一个中间表-成绩表
create table score(courseId int,studentId int,score decimal(3,1));
-- 向成绩表中插入数据
insert into score values(1,1,90);
如果想查找’甲’这个同学的’语文’成绩如何,该怎么做呢?
此时的查找过程就会更复杂,可以分为以下三个步骤
当然这三个步骤也是可以合并成一个的,想要合并成一个就要用到多表查询了,后面会学。
3.新增
语法:
INSERT INTO table_name [(column [, column ...])] SELECT ...
可以把其他select 查找的结果作为新增的数据。
-- 创建用户表1
create table user1(
id int primary key auto_increment,
name varchar(20),
decription varchar(1000)
);
-- 向use1表中插入数据
insert into user1 values(null,'曹操','乱世枭雄');
insert into user1 values(null,'刘备','仁德之主');
insert into user1 values(null,'孙权','年轻有为');
-- 创建用户表2
create table user2(name varchar(20),decription varchar(1000));
-- 在insert中包含一个子查询,子查询得到的列的数目,顺序,类型都得和被插入的表的列的数目,顺序,类型保持一致。列的名字一致不一致无所谓,只要数目,顺序,类型一致即可。
-- 将use1中的数据复制到use2中
insert into user2 select name,decription from user1;
-- 从use1表中查询信息
select name,decription from user1;
-- 查询user2表中的信息
select * from user2;
4.查询
4.1聚合查询
聚合查询就是把若干行结果按照一定的规则合并到一起,进行一些统计计算的查询。
4.1.1聚合函数
常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有
函数 | 说明 |
---|---|
count([distinct] expr) | 返回查询到的数据的数量 |
sum([disyinct] expr) | 返回查询到的数据的 总和,不是数字没有意义 |
avg([distinct] expr) | 返回查询到的数据的 平均值,不是数字没有意义 |
max([distinct] expr) | 返回查询到的数据的 最大值,不是数字没有意义 |
min([distinct] expr) | 返回查询到的数据的 最小值,不是数字没有意义 |
- count函数:计算结果的行数
select count(*) from user1;
-- count不计算null的值
-- count后不能有空格
select count(字段名) from user1;
count不计算null的值,如果是 * 就计算,如果指定为null的某一列,就不计算。
- sum函数:求和
- avg函数:求平均值
- max函数:求最大值
- min函数:求最小值
-- 创建学生表
create table student (id int primary key auto_increment,name varchar(20),score decimal(3,1));
-- 向学生表中插入数据
insert into student values(null,'曹操',89);
insert into student values(null,'刘备',90.5);
insert into student values(null,'孙权',88);
-- 求和
select sum(score) from student;
-- 求平均值
select avg(score) from student;
-- 求最大值
select max(score) from student;
-- 求最小值
select min(score) from student;
【练习】求成绩小于90分的学生的平均成绩
-- 求所有成绩小于90分的学生的平均成绩
select avg(score) from student where score<90;
聚合函数(count、sum、avg、max、min)如果没有使用group by就是针对整个查询结果集合进行统计计算,如果使用group by就会分组进行统计计算。
4.1.2 GROUP BY子句
group by:把得到的结果集按照一定的规则分组,如按照指定的列来分组,如果某两行的指定列值相同就会被分到一组。(可分成多个组)。
语法:
select column1, sum(column2), .. from table group by column1,column3;
-- 创建员工表结构
create table emp(
id int primary key auto_increment,
name varchar(20),
role varchar(20),
salary decimal(7,2)
);
-- 向员工表结构中插入数据
insert into emp values(null,'张老师','教师',110),(null,'高老师','教师',120),(null,'汤老师','教师',130);
insert into emp values(null,'赵老师','班主任',150),(null,'吴老师','班主任',160),(null,'李老师','班主任',140);
insert into emp values(null,'小王','运维',150),(null,'小赵','运维',160),(null,'小李','运维',140);
-- a)查询每个角色(岗位)
select role from emp;
-- b)针对每个角色进行分组,(角色相同的记录被分到同一组)
select role from emp group by role;
-- c)针对每一组分别求平均工资
select role,avg(salary) from emp group by role;
-- d)查询每个岗位对应的最高工资、最低工资、平均工资
select role,max(salary),min(salary),avg(salary) from emp group by role;
注意:group by进行操作完成之后,得到的查询结果和原来表中记录的结果的数量是不太一样的,一般会更少,毕竟它把一些相同的合并了。
4.1.3 having
group by 中也可以结合一些条件对数据进行进一步的筛选,不是使用where,而是使用having。
- 查询所有平均工资高于150的岗位和平均薪资。
select role, avg(salary) from emp group by role having avg(salary) > 150;
【疑问】:为什么这里的条件使用having而不使用where呢?
having 是针对group by聚合后的结果进行筛选;
where 是针对原始表中的每条记录都进行筛选。
4.2联合查询(多表查询)(难点+重点)
实现联合查询的基本机制:笛卡尔积。
实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积:
多表查询的过程:
1.根据要查找的数据,找到都需要哪些表;
2.针对这些表进行笛卡尔积的计算;
3.再基于where或者join on 后面的条件来对笛卡尔积中的记录进行筛选。
【注意】:如果针对两个比较大的表进行联合查询,笛卡尔积的计算开销会很大,最终的查询效率也就较低,所以不应该在生产环境上对大表进行联合查询。
注意:关联查询可以对关联表使用别名。
-- 创建表结构
-- 班级表:id name desc
create table classes (id int primary key auto_increment,name varchar(20),`desc` varchar(100));
-- 学生表:id sn name qq_email classes_id
create table student (id int primary key auto_increment,sn varchar(20),name varchar(20),qq_email varchar(20),classes_id int);
-- 课程表:id name
create table course (id int primary key auto_increment,name varchar(20));
-- 成绩表: score student_id course_id
create table score (score decimal(3,1),student_id int,course_id int);
-- 向班级表中插入数据
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');
-- 向学生表中插入数据
insert into student(sn, name, qq_email, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);
-- 向课程表中插入数据
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');
-- 向成绩表中插入数据
insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6);
4.2.1 内连接(重要)
语法
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;
为了更好地理解笛卡尔积和联合查询,以下三个练习不会直接给出结果而是通过一步一步的分析和查询,再最终得出结果。
【练习1】 查找名为"许仙"同学的所有成绩。
-- 姓名包含在student表中,分数包含在score表中,所以需要对这两个表进行联合查询。
-- 先进行笛卡尔积再进行筛选
-- 先看看两个表笛卡尔积的结果,直接借助SQL语句就可以
-- 多表查询时,写列的时候要写成[表名].[列名],表示哪张表中的哪一列
select student.id,student.name,score.student_id,score.score
from student,score;-- 得到两张表的笛卡尔积
在上面这个笛卡尔积中,发现大量的数据其实是没有意义的,那什么是有意义的什么是没意义的数据呢?
当student表中的id 和score 表中的student_id 字段对应,才是有意义的记录。
如:黑旋风李逵的数据就是有意义的数据,从上面的图表中可以看出,李逵的某个科目考了70.5,另一科考了98.5,再有一科考了33.0,而其他人的记录无法说明是什么意义。
想要干掉笛卡尔积中无意义的数据,只保留有意义的数据,加上一个where子句即可。
select student.id,student.name,score.student_id,score.score
from student,score
where student.id = score.student_id;
为了查找名为“许仙”的成绩信息,就在刚刚的where基础上再加一个条件,筛选姓名。
select student.id,student.name,score.student_id,score.score
from student,score
where student.id = score.student_id and student.name = '许仙';
最终答案:
多表查询 另外一种写法,使用 join on .
select student.id,student.name,score.student_id,score.score
from student
join score on student.id = score.student_id and student.name = '许仙';
【练习2】查找所有同学的总成绩,及同学的个人基本信息。
-- 学生信息包含在student表中,成绩包含在score表中,所以需要对这两个表进行联合查询(笛卡尔积)。
-- 先进行笛卡尔积,再进行筛选
-- 筛选条件:1.按照学生id来筛选,干掉笛卡尔积中不必要的数据;
-- 2.按照学生id进行group by,求每个同学的总成绩
解决思路:
-- 1.先直接进行联合查找,此时没有任何条件,得到的就是笛卡尔积
select student.id,student.name,score.student_id,score.score
from student,score;
-- 2.再根据student.id 进行筛选,把不必要的记录都干掉,
select student.id,student.name,score.student_id,score.score
from student,score
where student.id = score.student_id;
-- 3.按照student.id进行group by
select student.id,student.name,score.student_id,score.score
from student,score
where student.id = score.student_id group by student.id;
-- group by 之后得到的记录数目肯定要比原来少,如果某一列若干行的值已经相同了,group by没影响,如果某一个列不相同,group by 最终只剩下一条记录。
-- 4.最终结果:如果要是求每个同学的总成绩,其实也不受影响。
select student.id,student.name,sum(score.score)
from student,score
where student.id = score.student_id
group by student.id;-- 针对score聚类之后再求和
最终答案:
【练习3】查询所有学生的每一科成绩,及学生的个人信息。
这个题涉及到了三张表,学生姓名,科目名称,对应的成绩 (student表、course表、score表)。
解决思路:
-- 1.先针对三张表进行联合查找,此时没有任何条件,得到的就是笛卡尔积,但是这时得到的是一个非常大的笛卡尔积,并且大部分数据都是无意义的
select student.id,student.name,course.id,course.name,score.student_id,score.course_id,score.score
from student,course,score;
-- 2.按照student.id 和 score.student_id,针对笛卡尔积数据进行筛选
select student.id,student.name,course.id,course.name,score.student_id,score.course_id,score.score
from student,course,score
where student.id = score.student_id; -- 在这些记录中course.id和course_id不对应的话也是无意义的数据,所以还需要根据课程id再去筛选数据;
-- 3. 按照student.id 和 score.student_id 及 course.id 和 score.course_id,针对笛卡尔积数据进行筛选
select student.id,student.name,course.id,course.name,score.student_id,score.course_id,score.score
from student,course,score
where student.id = score.student_id and course.id = score.course_id;
-- 4.最终答案:去掉重复的列,只保留需要的列
select student.name,course.name,score.score
from student,course,score
where student.id = score.student_id and course.id = score.course_id;
最终结果:
![image-20211101122730463](https://i-blog.csdnimg.cn/blog_migrate/6ed537a23a8c046777e5da13cd74566a.png)
![image-20211101123630060](https://i-blog.csdnimg.cn/blog_migrate/1ac6c0d8e2480e9cfbbdc12e4813eecb.png)
- 当前我们这种进行笛卡尔积之后再按照id筛选,这样的筛选结果一定是同时在两张表中都出现过的记录,这种方式成为内连接。
4.2.2外连接
外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示我们就说是右外连接。
语法:
-- 左外连接,表1完全显示
select 列名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 列名 from 表名1 right join 表名2 on 连接条件;
【练习1】查询所有同学的成绩,及同学的个人信息,如果该同学没有成绩,也需要显示
-- 左外连接方式
select * from student stu left join score sco on stu.id = sco.student_id;
-- 右外连接方式
select * from score sco right join student stu on stu.id = sco.student_id;
-- 学生表、成绩表、课程表3张表关联查询的方式
select stu.id, stu.sn, stu.name, stu.qq_email, sco.score, sco.course_id, cou.name
from student stu
left join score sco on stu.id = sco.student_id
left join course cou on sco.course_id = cou.id
order by
stu.id;
如何理解内、外、左、右连接?(根据例子大致说一下)
内连接:同时在student 和 score表中存在的数据才能查到。
外连接:如果有些数据在student中存在,在score中不存在,或者在student中不存在,在score中存在,这样的记录也能查出来;
左连接:如果有些数据在student中存在,在score中不存在,这样的记录能查出来;
在student中不存在,在score中存在,这样的记录查不出来;
右连接:如果有些数据在student中存在,在score中不存在,这样的记录查不出来;
在student中不存在,在score中存在,这样的记录能查出来;
4.2.3自连接
自连接,顾名思义就是自己连接自己,它是指在同一张表连接自身进行查询。
有时候虽然我们会针对一张表来进行查询,但是有的时候为了去满足一些更加复杂的查找需求,我们需要把单表查询模拟成一个多表查询的过程,借助自连接来针对自己和自己进行笛卡尔积,再去进行一些数据筛选。
【练习1】找出所有“计算机原理”成绩比“Java”成绩高的同学的成绩信息
思路描述:按照课程名字找到课程id,拿着课程id再去成绩表中去找,看看计算机原理和Java所对应的信息是哪些,再去筛选某个同学,看哪个同学的计算机原理成绩高于Java成绩。
思路分析:
1).先找到Java和计算机原理课程id
-- 先找到Java和计算机原理课程id
select * from course where name='java';
select * from course where name='计算机原理';
-- a)针对score表自身进行笛卡尔积
select s1.student_id,s1.score,s1.course_id,s2.student_id,s2.score,s2.course_id
from score s1,score s2;
-- b)加上学生id的限制,将学生id和学生id对应,将无意义的数据筛选出去
select s1.student_id,s1.score,s1.course_id,s2.student_id,s2.score,s2.course_id
from score s1,score s2
where s1.student_id=s2.student_id;
-- c)加上课程id的限制,将课程id和课程id对应,将无意义的数据筛选出去
select s1.student_id,s1.score,s1.course_id,s2.student_id,s2.score,s2.course_id
from score s1,score s2
where s1.student_id=s2.student_id and s1.course_id = 3 and s2.course_id=1;
--
2).按照课程id在成绩表中筛选数据
-- d)再按照分数大小进行比较,得到最终结果
select s1.student_id,s1.score,s1.course_id,s2.student_id,s2.score,s2.course_id
from score s1,score s2
where s1.student_id=s2.student_id and s1.course_id = 3 and s2.course_id=1 and s1.score > s2.score;
-- e)也可以去掉不必要的列,找出所有“计算机原理”成绩比“Java”成绩高的同学的id
select s1.student_id
from score s1,score s2
where s1.student_id=s2.student_id and s1.course_id = 3 and s2.course_id=1 and s1.score > s2.score;
自连接本质上相当于把同一列中的两行记录转换成不同列的同一行记录,即把多行数据转化成一行中的多列数据。
每一步的过程图示:
4.2.4子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。相当于把多个查询语句结合到一起。
-
单行子查询:返回一行记录的子查询,即子查询的结果中只有一行。
【练习1】查询与“不想毕业”同学的同班同学。
-- 思路描述:和“不想毕业”这位同学的班级id一样的都是“不想毕业”这位同学的同班同学。 -- a)先查询出“不想毕业”这位同学的班级id select classes_id from student where name='不想毕业'; -- b)进行子查询,查询和“不想毕业”这位同学的班级id一样的学生 select name from student where classes_id = (select classes_id from student where name ='不想毕业');
-
多行子查询:返回多行记录的子查询。
【练习2】查询”语文“或者”英文“课程的成绩信息。
第一种实现方式:借助in关键字的方式来进行子查询。
-- a)先找到语文或者英文对应的课程id
select id
from course
where name='语文' or name= '英文';
-- b)再查询”语文“或者”英文“课程的成绩信息
select *
from score
where course_id in (select id from course where name='语文' or name= '英文');-- 语文和英文所对应的具体的课程信息
借助in的方式来进行子查询的执行过程是:先执行子查询,把子查询的结果保存到内存中,再进行主查询,再结合刚才子查询的结果来筛选最终结果。
第二种实现方式:借助exists关键字完成子查询。
select *
from score
where exists(select score.course_id from course
where (name = '语文' or name = '英文') and course.id = score.course_id);
借助exists完成子查询的执行过程是:先执行主查询,再触发子查询,再对两个结果(主表和子表)进行综合的筛选。
如何判断何时使用in 何时使用exists呢?
- 如果子表查询的结果集合比较小,就是用in;
- 如果子表查询的结果集合比较大,而主表的集合小,就是用exists;
- 不过,一般情况下都是借助in的方式来完成子查询,特殊情况下再借助exists完成子查询,因为使用exists写起来比in复杂,所以更推荐使用in。
4.2.5合并查询
合并查询:相当于把多个查询的结果集合,合并成一个集合,也就是把多个查询语句的查询结果借助union联合到一起,需要保证多个结果集之间的字段类型和数目都得一致。
在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用UNION和UNION ALL时,前后查询的结果集中,字段需要一致。
- union关键字:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行
【练习1】查询id小于3,或者名字为“英文”的课程
-- 使用or
select * from course where id < 3 or name = '英文';
-- 使用union:把两张表的查询结果合并到一起,去除重复数据
select * from course where id < 3
union
select * from course where name = '英文';
如果筛选条件非常简单,直接使用or就行,如果筛选条件比较复杂,可以使用使用union.
如果两个查询结果中存在相同的记录,就会只保留一个,相当于自动进行了去重,如果不想去重,可以使用union all即可。
- union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行.
【练习2】查询id小于3,或者名字为“Java”的课程
-- 使用union all:不去除重复数据
select * from course where id < 3
union all
select * from course where name='java';
5.内容重点总结
- 数据库约束
约束类型 | 说明 | 示例 |
---|---|---|
NULL约束 | 使用not null 指定列不为空 | name varchar(20) not null, |
unique 唯一约束 | 指定列为唯一的不重复的 | name varchar(20) unique, |
default默认值约束 | 指定列为空时的默认值 | age int default 20, |
主键约束 | not null 和 unique的结合 | id int primary key, |
外键约束 | 关联其他表的主键或唯一键 | foreign key (字段名) references 主表(列) |
check约束(了解即可) | 保证列中的值符合指定的条件 | check(sex = ‘男’ or sex = ‘女’) |
- 表的关系
一对一
一对多
多对多
-
新增
insert into 表名 [(column [, column ...])] select ...
-
查询
1.聚合查询:max 、 min 、avg 、count 、sum
2.分组查询:group by … having …
3.内连接
-- inner 可以缺省
select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 and 其他条件;
select 字段 from 表1 别名1,表2 别名2 where 连接条件 and 其他条件;
4.外连接
-- 左外连接,表1完全显示
select 列名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 列名 from 表名1 right join 表名2 on 连接条件;
5.自连接
select ... from 表1,表1 where 条件
select ... from 表1 join 表1 on 条件
6.子查询
-- 单行子查询
select ... from 表1 where 字段1 = (select ... from ...);
-- [NOT] IN
select ... from 表1 where 字段1 in (select ... from ...);
-- [NOT] EXISTS
select ... from 表1 where exists (select ... from ... where 条件);
-- 临时表:form子句中的子查询
select ... from 表1, (select ... from ...) as tmp where 条件
7.合并查询
-- UNION:去除重复数据
select ... from ... where 条件
union
select ... from ... where 条件
-- UNION ALL:不去重
select ... from ... where 条件
union all
select ... from ... where 条件
-- 使用UNION和UNION ALL时,前后查询的结果集中,字段需要一致
SQL查询中各个关键字的执行先后顺序: from > on> join > where > group by > with > having >
select > distinct > order by > limit
--SQL语言的特点:不需要用户来指定一步一步该如何执行,只需要告诉数据库,最终想要啥数据即可。像C/Java则需告诉计算机每一步都该如何执行。
- 光看语法容易看不懂,还是要结合例子,多看多练习!