一、数据库约束

约束就是数据库在使用的时候,对于里面能够存的数据提出的要求和限制,程序猿就可以借助约束来完成更好的校验

1、约束类型

① NULL约束

NOT NULL - 指示某列不能存储 NULL 值,插入会直接报错

  • 给id这一列设为not null 之后,此时这里的值就变成NO了

  • 当尝试插入空值的时候,就直接会报错,插入失败

  • NOT NULL是可以给任意个列来进行设置,不仅仅是这一个列


② UNIQUE:唯一约束

UNIQUE - 保证某列的每行必须有唯一的值,尝试插入也会报错。



③ DEFAULT:默认值约束

DEFAULT - 规定没有给列赋值时的默认值

  • MySQL中,默认的默认值,是 NULL


  • 此处也可以把默认的默认值给改成其他咱们需要的内容


④ PRIMARY KEY:主键约束

PRIMARY KEY - NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
主键约束,相当于数据的唯一身份标识。类似于身份证号码 / 手机号码。
这个是咱们日常开发的时候最常使用的约束!最重要的约束。
创建表的时候,很多时候都需要指定主键。

  • 对于一个表来说,只能有一个列被指定为主键

  • 关于主键,典型的用法,就是直接使用1,2,3,4整数递增的方式来进行表示
    MySQL里面对于这种递增的主键,是有内置支持的,称为 "自增主键"

  • 当设定好自增主键之后,此时插入的记录,就可以不指定自增主键的值了(直接使用null 来表示),交给 mysql自行分配即可

  • 依靠mysql的自增主键来分配的
    每次新增一个新的记录,都会产生一个自增的id

  • 自增主键也是可以手动指定id的,一旦指定过之后,后续新插入的数据就都是从10之后来排了3-10之间的就用不了


上面说的这些约束,都是针对每个列单独设置的,只是针对这个列来说是这样的,不同的列之间没有影响


⑥ FOREIGN KEY:外键约束

FOREIGN KEY - 保证一个表中的数据匹配另一个表中的值的参照完整性。
外键用于关联其他表的主键或唯一键


  • 构造一个学生表,来指定一下外键约束

  • 在student表中插入数据:

  • 修改 student 表中的 Classid:


  • 刚才都是针对子表来操作,外键约束同样也在约束父表


外键约束的工作原理:

在子表中插入新的记录的时候,就会先根据对应的值,在父表中先查询,查询到之后,才能够执行后续的插入

这里的查询操作,可能是一个成本较高的操作(比较耗时),外键约束其实要求,父表中被依赖的这一列,必须要有索引,有了索引就能大大的提高查询速度~

class 表的 classld 这一列,得是 primary key 或者 unique (有了这俩约束的列,就会自动的创建出索引了)

  • 想象一个场景,购物

商品表 (保存了商品信息) :商品id 商品名字…
订单表 (保存了订单信息) :订单id 商品id …
订单是不应该被删除的!用户随时可能要看看这里的内容

按照上面描述的外键约束的关系
就可以认为,商品表就是父表,订单表就是子表。订单表中的商品id应该是在商品表的商品id中存在
好单,买好东西,很久之后,我发现,这个商品下架了(被从商品表中删除了),这个数据,是如何删除的
按照刚才说的外键约束,—旦建立好了约束关系,此时父表的记录不能随便删除如果这个记录被子表依赖了,此时就无法删除了~~

采取的办法,不是真正的删除,而是 “逻辑上的删除”
给商品表加一个列 isOk 。如果这—列值为1,表示这是一个有效记录。如果这一列值为0,表示这是一个无效记录(相当于被删除了)
如果不是真的删除掉,而只是逻辑上删除的话,这个记录不是就始终存在嘛?这不就会导致数据库里面的内容越来越多,逐渐膨胀,非常浪费硬盘空间嘛?
硬盘空间,不值钱!远远不如人力成本高


练习:

设计一个学校食堂管理系统
学校食堂管理系统,包含食堂表,食堂仓口表,仓口收费记录表

create table canteen (id int primary key auto_increment, name varchar(20));create table canteen_window (id int primary key auto_increment, name varchar(20), window_id int, foreign key(window_id) references canteen(id));create table canteen_charge (id int primary key auto_increment, price int, charge_date datetime, canteen_window_id int, foreign key(canteen_window_id) references canteen_window(id));insert into canteen_charge values (null, 20, '2022-02-02 12:12:12', 1);
insert into canteen_charge values (null, 15, '2022-02-03 13:13:13', 2);
insert into canteen_charge values (null, 30, '2022-02-04 15:15:15', 3);

设计一个车辆违章系统
车辆违章系统,包含用户表,车辆表,违章信息表。违章信息表中包含用户和车辆的违章信息

用户可以拥有多辆车,关系为1:m,题目已经说明违章信息包括用户和车辆,说明违章信息表中要记录用户和车辆,一个用户可以有多次违章记录,用户与违章记录关系为1:m,一辆车也可以有多次违章记录,车辆与违章记录关系也为1:m

create table user (id int primary key, name varchar(20));create table cars (id int primary key, name varchar(20), user_id int, foreign key(user_id) references user(id));create table vehicle_violation_information (user_id int,cars_id int,foreign key(user_id) references user(id),foreign key(cars_id) references cars(id));insert into cars values(123, 'crown', 1);
insert into cars values(357, 'maybach', 2);
insert into cars values(789, 'ford', 1);insert into vehicle_violation_information values (1, 123), (2, 357);

设计一个学校宿舍管理系统
学校宿舍管理系统,要求包含宿舍信息,学生信息,每日的宿舍查房记录。

一个食堂有多个仓口卖饭,关系为1:m,每个仓口卖饭可以有很多次,仓口与收费记录也是1:m

create table dormitory (id int primary key);create table student (id int primary key,name varchar(20),dormitory_id int, foreign key(dormitory_id) references dormitory(id));create table records (id int primary key,dormitory_id int,status bit,record_time datetime,foreign key(dormitory_id) references dormitory(id));insert into dormitory values (301), (302);
insert into student values (1, 'zhangsan', 301), (2, 'lisi', 301), (3, 'wangwu', 301), (4, 'zhaoliu', 302);insert into records values (1, 301, 1, '2021-12-12 12:12:12');
insert into records values (2, 302, 0, '2021-12-12 13:13:13');mysql> select * from dormitory;
+-----+
| id  |
+-----+
| 301 |
| 302 |
+-----+
2 rows in set (0.00 sec)mysql> select * from student;
+----+----------+--------------+
| id | name     | dormitory_id |
+----+----------+--------------+
|  1 | zhangsan |          301 |
|  2 | lisi     |          301 |
|  3 | wangwu   |          301 |
|  4 | zhaoliu  |          302 |
+----+----------+--------------+
4 rows in set (0.00 sec)mysql> select * from records;
+----+--------------+--------+---------------------+
| id | dormitory_id | status | record_time         |
+----+--------------+--------+---------------------+
|  1 |          301 |       | 2021-12-12 12:12:12 |
|  2 |          302 |        | 2021-12-12 13:13:13 |
+----+--------------+--------+---------------------+
2 rows in set (0.00 sec)

设计一个考勤系统
考勤系统,包含员工表,考勤记录表

create table staff (id int primary key, name varchar(20));create table attenance (id int primary key, staff_id int, info_time datetime,foreign key(staff_id) references staff(id));insert into staff values (1, 'zhangsan'), (2, 'lisi');insert into attenance values (1, 001, '2021-03-03 9:00:00');
insert into attenance values (2, 002, '2021-03-03 9:00:00');mysql> select * from staff;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
+----+----------+
2 rows in set (0.00 sec)mysql> select * from attenance;
+----+----------+---------------------+
| id | staff_id | info_time           |
+----+----------+---------------------+
|  1 |        1 | 2021-03-03 09:00:00 |
|  2 |        2 | 2021-03-03 09:00:00 |
+----+----------+---------------------+
2 rows in set (0.00 sec)

二、表的设计

所谓的 “数据库设计” “表的设计” 其实就是根据实际的问题场景,把表给创建出来了

给你一个问题场景,如何设计数据库,如何设计表?
一个典型的通用的办法:先找出这个场景中涉及到的 “实体” 然后再来分析“实体之间的关系"
实体 => 对象
实体就可以视为是需求中的一些关键性的名词

一个典型的场景:学生管理系统

  1. 表示学生的基本信息
  2. 表示班级的基本信息.
  3. 表示学生学习的课程的基本信息

对于咱们找到的实体来说,就需要创建对应的表来表示相关的信息 (每个实体表,里面的基本信息,结合需求都是容易确定的)
很多时候,实体和实体之间,并不是孤立的,而是存在对应关系,这样的对应关系,也需要体现在表中 (实体之间的关系,这个是隐含的,是需要进一步分析才能想清楚的。这里实体之间的不同的关系,会对表的设计产生直接的影响)

实体之间的关系

  1. 一对一的关系
  2. —对多的关系
  3. 多对多的关系




三、新增

INSERT INTO table_name [(column [, column ...])] SELECT ...

和查询结合在一起的新增操作,把从上一个表中的查询结果,作为下一个表要插入的数据

案例1:创建一张用户表,设计有name姓名、email邮箱、sex性别、mobile手机号字段。需要把已有的
学生数据复制进来,可以复制的字段为name、qq_mail

-- 创建用户表
DROP TABLE IF EXISTS test_user;
CREATE TABLE test_user (id INT primary key auto_increment,name VARCHAR(20) comment '姓名',age INT comment '年龄',email VARCHAR(20) comment '邮箱',sex varchar(1) comment '性别',mobile varchar(20) comment '手机号'
);-- 将学生表中的所有数据复制到用户表
insert into test_user(name, email) select name, qq_mail from student;

案例2:把A的记录给插入到B中:

  • 在这个语句中,就会先执行查找。针对查找到的每个结果,都执行插入操作,插入到B中,我们需要保证,从A中查询出来的结果的列数和类型,和B表匹配

  • 接下来,把B的列的顺序调换一下,此时能否完成把A的数据给插入到B这个操作呢?只要保证A
    的查询结果的列的顺序和B对应
    即可

  • 本来A表中,id在前,name在后,和B的列的顺序不匹配,但是可以通过针对A进行指定列查询,从而可以保证查询结果的顺序能和B对上

另外,还可以给后面的 select 指定一些其他的条件 / 排序 /limit / 去重,插入的实际就是select执行结果的临时表,得保证插入之后数据是合理的


四、查询

1、聚合查询

1.1、聚合函数

把多行之间的数据,给进行聚合
MySQL内置了一些聚合函数,可以让我们直接来使用
常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:

函数 说明
COUNT([DISTINCT] expr) 返回查询结果有多少行
SUM([DISTINCT] expr) 返回查询到的数据的 总和,不是数字没有意义
AVG([DISTINCT] expr) 返回查询到的数据的 平均值,不是数字没有意义
MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义
MIN([DISTINCT] expr) 返回查询到的数据的 最小值,不是数字没有意义

案例:

-- 创建考试成绩表
DROP TABLE IF EXISTS exam_result;
CREATE TABLE exam_result (
id INT,name VARCHAR(20),chinese DECIMAL(3,1),math DECIMAL(3,1),english DECIMAL(3,1)
);-- 插入测试数据
INSERT INTO exam_result (id,name, chinese, math, english) VALUES-> (1,'唐三藏', 67, 98, 56),-> (2,'孙悟空', 87.5, 78, 77),-> (3,'猪悟能', 88, 98.5, 90),-> (4,'曹孟德', 82, 84, 67),-> (5,'刘玄德', 55.5, 85, 45),-> (6,'孙权', 70, 73, 78.5),-> (7,'宋公明', 75, 65, 30);

count
-就相当于是针对 select * from exam_resul t的结果集合进行计算行数~

  • count这里的参数不一定非要写作*也可以指定某个列

sum

把这一列的若干行,进行相加

  • 这个操作仍然是表达式查询

  • 聚合函数,也是表达式中的一个部分

  • sum这个操作只能针对数字进行运算,不能针对字符串来进行

where

聚合函数,还可以搭配where字句来使用.可以基于条件进行筛选,把筛选结果,在进行聚合


2、GROUP BY子句

2.1、group by

根据行的值,对数据进行分组.把值相同的行都归为一组

SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中

create table emp(id int primary key auto_increment,name varchar(20) not null,role varchar(20) not null,salary numeric(11,2)
);insert into emp(name, role, salary) values('马云','服务员', 1000.20),('马化腾','游戏陪玩', 2000.99),('孙悟空','游戏角色', 999.11),('猪无能','游戏角色', 333.5),('沙和尚','游戏角色', 700.33),('隔壁老王','董事长', 12000.66);

1、查询每个角色的最高工资、最低工资和平均工资

按照岗位,来进行分组

一个sql的执行过程,具体的执行顺序,和我们书写的顺序并不完全一致

计算avg 的时候, NULL这样的记录是不计入其中的,不会影响到平均值的结果


2.2、having

针对分组之后,得到的结果,可以通过having来进行指定条件

group by是可以使用where.只不过 where是在分组之前执行.如果要对分组之后的结果进行条件筛选,就需要使用having

分组前:
分组之前指定条件:还是求每种角色,平均薪资,要去掉马云,这里就是先去掉马云,然后再分组,分组之前指定的条件,就要使用 where

可以看到,正好就是马云是服务员,把马云去掉之后,分组结果中,就少了服务员这个记录

分组之后指定条件筛选:
求每种角色,平均薪资,只保留平均薪资1w以下,这里就是得先分组计算,知道了平均工资,才能进一步的筛选 (分组之后,指定的条件,就需要使用having 了)


很明显的看到,董事长这个平均薪资超过1w的记录已经没有了~~


3、联合查询

3.1、笛卡尔积

实际开发中往往数据来自不同的表,所以需要多表联合查询。多表查询是对多张表的数据取笛卡尔积

笛卡尔积 (多表查询中的核心操作), 笛卡尔积是针对任意两张表之间进行的运算

笛卡尔积的运算过程:
先拿第一张表的第一条记录,和第二张表的每个记录,分别组合,得到了一组新的记录,继续再拿第一张表的第二条记录


3.2、使用

如何在SQL中进行笛卡尔积:最简单的做法,就是直接 select * from表名,表名 之间使用逗号分割

笛卡尔积,是两张表中数据尽可能的排列组合得到的,
在这些排列组合中,仔细看,有没有一些数据是我们需要的,另外一些数据是没1意义的呢?
笛卡尔积是一个单纯无脑的排列组合,这里的组合结果不一定都是有意义的数据两张表中,都有classld这一列classld 的值对应相等的记录,其实就是应该要保留的记录,像这里的classld相等这样的条件,就称为 "连接条件"带有连接条件的笛卡尔积,其实就是 “多表查询了”

如果笛卡尔积中的两个列名字相同,在写条件的时候就可以通过表名.列名的方式来访问
如果列名不会混淆(不是同名的),可以用表名.列名,也可以省略表名

  • 修改后:

当在代码中加上筛选条件之后,很明显的看到,记录里就只剩下4条咱们需要的数据了


在最终的查询结果中,一般就只是需要一部分列来显示,就要哪个列就显式制定哪个列就行了


3.3、多表查询

drop table if exists classes;
drop table if exists student;
drop table if exists course;
drop table if exists score;create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));create table student (id int primary key auto_increment, sn varchar(20),  name varchar(20), qq_mail varchar(20) ,classes_id int);create table course(id int primary key auto_increment, name varchar(20));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_mail, 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);

在这个场景中,涉及到到的实体,主要是三个
学生
班级
课程
学生和班级是—对多的关系
学生和课程是多对多的关系
分数表,其实就是学生和课程之间的关联表

  • desc:

  • select:


3.3.1、内连接

1)查询“许仙”同学的 成绩

select sco.score from student stu inner join score sco on stu.id=sco.student_id
and stu.name='许仙';
-- 或者
select sco.score from student stu, score sco where stu.id=sco.student_id and
stu.name='许仙';

许仙选了很多课,就需要在学生表中获取到学生姓名,在分数表中,获取到分数信息心,这里就需要针对学生表和分数表进行笛卡尔积

当前笛卡尔积,里面的东西太多了 160行,仔细观察就能发现,在当前的这两张表里,都存在学生id这个列,按照前面总结的规律,应该指定这两个id 匹配,才保留记录,不匹配的就属于是排列组合直接生成的无效数据

这个里面就体现出了,每个学生的每门课程,分数分别是多少
再加一个条件:


此时就是只包含许仙的每门课的成绩了,只需要许仙的成绩,其他列就都不要了只保留名字和分数

实现刚才这个多表查询,直接from 多张表,是一种写法,除此之外,还有另外一种写法.基于join 这样的关键字,也能实现多表查询


2)查询所有同学的总成绩,及同学的个人信息:

-- 成绩表对学生表是多对1关系,查询总成绩是根据成绩表的同学id来进行分组的
SELECT
stu.sn,
stu.NAME,
stu.qq_mail,
sum( sco.score )
FROM
student stu
JOIN score sco ON stu.id = sco.student_id
GROUP BY
sco.student_id;

这个案例要在多表查询的基础上,再加上一个聚合查询

这个效果就是显示出每个同学的每个科目的分数,此处可以看到,同学的分数,是按照行的方式来排列的:


加上 group by id 之后,可以看到,记录的行数明显变少了.每个同学只有一行数据了


分组之后,可以看到,当前这里的score列并不是总成绩,而是每个分组中的第一条记录,此处要想得到总成绩,就需要进行sum操作:


3)查询所有同学的成绩,及同学的个人信息:

这里不光要查询出同学的名字,还有课程名字、分数
这个时候。就涉及到三张表的联合查询了
同学名字 => 学生表
课程名字 => 课程表
分数 => 分数表
三张表算笛卡尔积和两张表,规则都一样

当前这个表就列出了每个同学的每个课程拿到的分数.同时带有课程的名字,去掉不必要的列,只保留关注的关键列:


如果是 join on 的写法,能否针对三张表进行联合:
from表1 join表2 on条件join表3 on条件

select student.name, course.name, score.score from student join score on student.id = score.student_id join course on score.course_id = course.id;

上面说的这个from 多个表 where 写法叫做 内连接
使用join on 的写法,既可以表示 内连接,还可以表示 外连接


3.3.2、外连接

select列from表1 inner join表2 on条件;

inner join表示是 “内连接” 其中inner可以省略

select列 from表1 left join表2 on条件; -- 左外连接
select列 from表1 right join表2 on条件; -- 右外连接


按照之前介绍过的笛卡尔积操作,很明显,这里的记录是少了一个4的同学的记录:


上面的写法,就相当于是一个inner join

left join:


通过刚才的例子,可以看到 left joininner join 之间的区别,

inner join要求的是两个表里都同时有的数据

left join以左侧的表为主,会尽可能的把左侧的表的记录都列出来,大不了后侧的表的对应列填成NULL
right join 也是类似:以右侧的表为主,尽可能把右侧的记录都列出来,大不了左侧的表对应的列填成NULL


内连接里的记录就只是包含两个表中同时拥有的记录:


左外连接就是以左侧表为主,左侧表中的每个记录都在左外连接中有体现


右外连接就是以右侧表为主,右侧表的每个记录都在结果中有体现

是否存在一种连接,能够得到这种效果呢?这种称为 “全外连接” ,但是,mysql不支持


3.3.3、自连接

自连接是指在同一张表连接自身进行查询

什么时候需要使用自连接:自连接的本质其实是把行和行之间的比较条件,转换成列和列

示例:显示所有“计算机原理”成绩比“Java”成绩高的成绩信息

SQL指定条件,都是按照列和列之间进行指定的
而这个问题下的表,科目之间已经不是列了,而是行了
在这个问题中,可以看到,这里的条件是按照行的方式来排列的,为了解决这个问题,就需要把行,给转换成列把行转换成列,就可以用到 “自连接"
自连接同名,就指定两个名字:

select * from score as s1, score as s2;

共有四百条记录,

按照 student_id 进行连接条件之后产生的笛卡尔积:
共62条记录


本来这里的 98.5 和 70.5 是同一个列的两行,经过了笛卡尔积之后,已经分布到两个列中了,是当前这里的这两列,中间还是有着不少的无效数据的,为了能够更好的进行比较,再加上一些筛选条件,比如,就让s1的课程id只保留3的记录,就让s2的课程id只保留1的记录:

最后加上判断大小:

select * from score as s1, score as s2 where s1.student_id = s2.student_idand s1.course_id = 3 and s2.course_id = 1and s1.score > s2.score;


3.3.4、子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

1) 单行子查询:返回一行记录的子查询

查询与“不想毕业” 同学的同班同学:

先知道不想毕业这个同学的班级id,然后根据班级id在学生表中筛选同id的同学:


合并:


2)多行子查询:返回多行记录的子查询
案例:查询“语文”或“英文”课程的成绩信息

先查询语文和英文课程 id,再根据课程 id 找到对应的成绩信息:


合并:

select * from score where course_id in (select id from course where name = '语文' or name = '英文');


1.可以使用多列包含:

-- 插入重复的分数:score, student_id, course_id列重复
insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),
-- 菩提老祖
(60, 2, 1);-- 查询重复的分数
SELECT*
FROMscore
WHERE( score, student_id, course_id ) IN ( SELECT score, student_id,
course_id FROM score GROUP BY score, student_id, course_id HAVING
count( 0 ) > 1 );

2.[NOT] EXISTS关键字:

-- 使用 EXISTS
select * from score sco where exists (select sco.id from course cou where (name='语文' or name='英文') and cou.id = sco.course_id);-- 使用 NOT EXISTS
select * from score sco where not exists (select sco.id from course cou where (name!='语文' and name!='英文') and cou.id = sco.course_id);

在from子句中使用子查询:子查询语句出现在from子句中。这里要用到数据查询的技巧,把一个子查询当做一个临时表使用。
查询所有比“中文系2019级3班”平均分高的成绩信息:

-- 获取“中文系2019级3班”的平均分,将其看作临时表
SELECTavg( sco.score ) score
FROMscore scoJOIN student stu ON sco.student_id = stu.idJOIN classes cls ON stu.classes_id = cls.id
WHEREcls.NAME = '中文系2019级3班';

查询成绩表中,比以上临时表平均分高的成绩:

SELECT*
FROMscore sco,(SELECTavg( sco.score ) scoreFROMscore scoJOIN student stu ON sco.student_id = stu.idJOIN classes cls ON stu.classes_id = cls.idWHEREcls.NAME = '中文系2019级3班') tmpWHEREsco.score > tmp.score;

3.3.5、合并查询

在实际应用中,为了合并多个 select 的执行结果,可以使用集合操作符 unionunion all 。通过 union 把两个 sq l的查询结果给合并到一起了,合并的前提是两个sql查询的列得是对应的。

union :该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行

案例:查询id小于3,或者名字为“英文”的课程:


也可以使用or来替换,使用or的时候,必须保证你是针对同一个表来指定的多个条件查询,union 不一定是针对同一张表

union all : 该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行

MySQL 数据库约束、聚合查询、多表查询相关推荐

  1. MySQL数据库设计概念(多表查询事务操作)

    每天进步一点点 数据库设计概念 数据库设计简介 表关系(多对多) 表关系(一对多) 表关系之一对一 多表查询 笛卡尔积现象 内连接查询 外连接查询 嵌套查询(子查询) 事务操作 事务的概念 手动提交事 ...

  2. MySQL数据库学习(6) -- 表查询关键词

    前期表准备 # 如果cmd窗口展示数据时,窗口最大,展示数据的虚表仍有错位,应使用 \G 分行显示 select * from t1\G;# 个别电脑在插入中文的时候会出现乱码或者空白的现象,可以将字 ...

  3. mysql数据库练习第二章----二表查询

    1.分别创建class表和stuent表 class表 class_id 主键.自增 class_name char(20) teacher char(20) student表 sid int,主键, ...

  4. MySQL数据库基础(五)——SQL查询

    MySQL数据库基础(五)--SQL查询 一.单表查询 1.查询所有字段 在SELECT语句中使用星号""通配符查询所有字段 在SELECT语句中指定所有字段 select fro ...

  5. MySQL学习笔记06【多表查询、子查询、多表查询练习】

    MySQL 文档-黑马程序员(腾讯微云):https://share.weiyun.com/RaCdIwas 1-MySQL基础.pdf.2-MySQL约束与设计.pdf.3-MySQL多表查询与事务 ...

  6. 数据库一对多做链接去重_数据库单表查询-多表查询

    """ 1.字段修改 alter modify alter change alter add ''|first|after alter drop 2.表关系: 一对一:外 ...

  7. day44 数据库单表查询-多表查询

    目录 复习 今日内容 单表查询 连表查询 复习 """ 1.字段修改alter modifyalter changealter add ''|first|afteralt ...

  8. MySQL 实现多张无关联表查询数据并分页

    MySQL 实现多张无关联表查询数据并分页 1.功能需求 在三张没有主外键关联的表中取出自己想要的数据,并且分页. 2.数据库表结构 水果表: 坚果表: 饮料表: 主要用UNION AL UNION ...

  9. 数据库的实例化操作——员工信息的查询——简单表查询(二)

    员工信息的查询--简单表查询(二) 表信息查看  -->表信息 简单查询 查询所有的职位 select distinct job from emp;      查询出来的job是所有人的职位,用 ...

  10. MySql的复习(五):联表查询和子查询

    MySql的复习(五):联表查询和子查询 查询结果去重 关于查询结果的去重:distinct关键字 select distinct job from emp; // distinct关键字去除重复记录 ...

最新文章

  1. java反射的编译过程_Java反射机制小结和实际操作
  2. 每天一道LeetCode-----找到给定数组的连续子数组,使这个子数组的和最大,要求复杂度为O(n)
  3. c++读出像素矩阵_Python传numpy矩阵调c++(求3D图像连通区域)
  4. swift 2.2 语法 (上)
  5. 09 | 自编码器:让模型拥有属于自己的表达和语言
  6. css文字溢出部分在另一个div显示(代码篇)
  7. imx6 配置串口波特率_stm32异步串口(uart)通讯基本操作
  8. list 分组_Todo List(源码已上传git): 待办事项自定义分组 - 第三章
  9. linux的工程管理器是,Linux工程管理器——make
  10. C语言从入门到精通保姆级教程(2021版上)
  11. autohotkey循环
  12. 全志(Allwinner) A40i使用千兆网的配置
  13. 考研数学张宇常说的段子和道理,自己看视频的时候整理的(欢迎指正、补充)
  14. lora 网关 linux,选择LoRaWAN网关的5大关键 很重要!
  15. 网路新年贺词_文伟_新浪博客
  16. 解决 No module named 'tensorflow_serving' 问题
  17. Android补间动画原理介绍
  18. 个人看过的动漫、动画电影推荐
  19. JAVA:实现线性丢番图方程求解器算法(附完整源码)
  20. 中年失业的处境有多艰难,成年人的生活不容易,且行且珍惜

热门文章

  1. matlab的三条线如何区分,电线三根线颜色如何区分
  2. 2021-2025年中国口腔清洁用品行业市场供需与战略研究报告
  3. 波士顿房价数据集怎么不见了?
  4. 旧电脑装html5,8年前老电脑如何升级?实战近十年的老电脑升级方案
  5. 【Gragph Data Mining】VF2算法 — 图同构匹配的算法
  6. Unity Animator
  7. 大数据安全:Ranger与Sentry使用区别
  8. LeetCode刷题日记2021-11-22/384. 打乱数组-数据结构
  9. memset linux 头文件,linux中memset的正确用法
  10. Linux重启网卡失败解决办法