文章目录
- [1. create](#1. create)
- [1.1 单行数据 + 全列插入](#1.1 单行数据 + 全列插入)
- [1.2 多行数据 + 指定列插入](#1.2 多行数据 + 指定列插入)
- [1.3 插入更新](#1.3 插入更新)
- [1.4 插入替换](#1.4 插入替换)
- [2. retrieve](#2. retrieve)
- [2.1 select列](#2.1 select列)
- [2.11 全列查询](#2.11 全列查询)
- [2.12 指定列查询](#2.12 指定列查询)
- [2.13 查询字段为表达式](#2.13 查询字段为表达式)
- [2.14 结果去重](#2.14 结果去重)
- [2.2 where条件](#2.2 where条件)
- [2.21 各种成绩查询](#2.21 各种成绩查询)
- [2.22 null的查询](#2.22 null的查询)
- [2.3 结果排序](#2.3 结果排序)
- [2.4 筛选分页结果](#2.4 筛选分页结果)
- [3. update](#3. update)
- [4. delete](#4. delete)
- [5. 插入查询结果](#5. 插入查询结果)
- [6. 聚合函数](#6. 聚合函数)
- [6.1 无分组聚合](#6.1 无分组聚合)
- [6.2 分组聚合](#6.2 分组聚合)
1. create
语法:
mysql
insert [into] table_name [(column [, column] ...)] values (value_list) [, (values_list)]...
[]
里面的内容可以省略,values
两侧平衡(可理解为扁担),左侧表示要向哪列插入,右侧表示插入的数据
1.1 单行数据 + 全列插入
创建一个学生表:
mysql
mysql> create table students (
-> id int unsigned primary key auto_increment,
-> sn int unsigned unique key,
-> name varchar(20) not null,
-> telephone varchar(32) unique key
-> );
一次插入一行数据:
mysql
mysql> insert into students(sn, name, telephone) values (23402101, '张三', '2024001');
mysql> insert into students values (10, 23402110, '李四', '2024010'); # 全列插入
values
左侧忽略时就表明要进行全列插入,每一列都要指定数据
1.2 多行数据 + 指定列插入
mysql
mysql> insert into students values (11, 23402111, '王五', '2024011'), (12, 23402112, '赵六', '2024012');
values
右侧用逗号隔开,表明插入多行数据
1.3 插入更新
mysql
mysql> insert into students values (12, 23402122, '田七', '2024022'); #主键冲突
ERROR 1062 (23000): Duplicate entry '12' for key 'PRIMARY'
mysql> insert into students values (13, 23402113, '田七', '2024012'); # 唯一键冲突
ERROR 1062 (23000): Duplicate entry '2024012' for key 'telephone'
当插入时出现冲突的时候,可采用同步更新操作,语法:
mysql
insert into ... on duplicate key update column = value [, column = value] ...
mysql
mysql> insert into students values (12, 23402122, '田七', '2024022')
-> on duplicate key update sn=23402122, name='田七', telephone='202422';
-- 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
-- 1 row affected: 表中没有冲突数据,数据被插入
-- 2 row affected: 表中有冲突数据,并且数据已经被更新
可采用
select row_count()
查看受影响的行数
1.4 插入替换
如果主键或者唯一键没有冲突,则直接插入;
如果主键或者唯一键冲突,先删除,再插入:
mysql
mysql> replace into students (sn, name, telephone) values (234021015, '老八', 2024015);
Query OK, 1 row affected (0.01 sec)
mysql> replace into students (sn, name, telephone) values (234021015, '小八', 2024015);
Query OK, 2 rows affected (0.00 sec)
2. retrieve
mysql
mysql> create table exam_ret(
-> id int unsigned primary key auto_increment,
-> name varchar(20) not null,
-> chinese float default 0.0 comment '语文成绩',
-> math float default 0.0 comment '数学成绩',
-> english float default 0.0 comment '英语成绩'
-> );
mysql> insert into exam_ret (name, chinese, math, english) values
-> ('张三', 88, 84, 77),
-> ('李四', 75, 91, 66),
-> ('王五', 45, 82, 73),
-> ('赵六', 94, 42, 51),
-> ('田七', 62, 67, 98);
2.1 select列
2.11 全列查询
mysql
mysql> select * from exam_ret;
*
表示通配,在实际并不推荐采用*
进行全列查询
- 数据库服务一般在服务器上;
- 线上服务器数据库里面存储的数据量非常大
2.12 指定列查询
mysql
mysql> select name, math from exam_ret;
2.13 查询字段为表达式
mysql
mysql> select name, math, chinese+math+english from exam_ret;
也可也将表达式名称命名
mysqlmysql> select name, math, chinese+math+english as total from exam_ret;
mysqlmysql> select name 姓名, math 数学, chinese+math+english 总分 from exam_ret;
2.14 结果去重
mysql
mysql> select distinct chinese from exam_ret;
2.2 where条件
比较运算符:
运算符 | 说明 |
---|---|
>, >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1) |
!=, <> | 不等于 |
BETWEEN a0 AND a1 | 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1) |
IN (option, ...) | 如果是 option 中的任意一个,返回 TRUE(1) |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
LIKE | 模糊匹配。% 表示任意多个(包括 0 个)任意字符;_ 表示任意一个字符 |
逻辑运算符:
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0) |
2.21 各种成绩查询
++查找成绩不及格的同学:++
mysql
mysql> select name, chinese from exam_ret where chinese<60;
mysql> select name, math from exam_ret where math<60;
mysql> select name, english from exam_ret where english<60;
++查找语文成绩在[80,100]的同学:++
mysql
mysql> select name, chinese from exam_ret where chinese>=80 and chinese<=100;
mysql> select name, chinese from exam_ret where chinese between 80 and 100;
++查找指定英语成绩:++
mysql
mysql> select name, english from exam_ret where english=98 or english=97 or english=51;
mysql> select name, english from exam_ret where english in (98, 97, 51);
++查找姓张和张某:++
mysql
mysql> select name from exam_ret where name like '张%'; #姓孙
mysql> select name from exam_ret where name like '张_'; #孙某
++查找英文成绩好于英语成绩的同学:++
mysql
mysql> select name, chinese, english from exam_ret where chinese > english;
++查找总分小于225的同学:++
mysqlmysql> select name, chinese + math + english total from exam_ret where total<225; ERROR 1054 (42S22): Unknown column 'total' in 'where clause'
在上面的
sql
语句中,执行顺序是:
- 先执行
from
,要知道在哪个表当中筛选数据;- 再执行
where
,要知道筛选的条件,拿着条件去筛选;- 最后拿着条件去指定表里面的指定列筛选
所以这里报错不认识这个
total
别名
mysqlmysql> select name, total from exam_ret where chinese + math + english total<225; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'total<200' at line 1
上面这样也不行,因为对列做重命名,已经是最后一步了,将数据拿完,最后改一下名字
mysql
mysql> select name, chinese+math+english total from exam_ret where chinese+math+english<225;
++查找语文成绩大于80且不姓张的同学:++
mysql
mysql> select name,chinese from exam_ret where chinese>80 and name not like'张%';
++查找张某同学,其他的同学成绩必须>225且英语>80:++
mysql
mysql> select name, chinese, math, english, chinese+math+english total from exam_ret where name like '张_' or (chinese+math+english>225 and english>80);
2.22 null的查询
mysql
mysql> select * from t11 where name is null;
mysql> select * from t11 where name is not null;
null
表示没有,' '
表示有,但是是空串
2.3 结果排序
语法:
mysql
select ... from table_name [where ...] order by column [asc|desc], [...]
#asc 为升序(默认为asc)
#desc 为降序
如果有
null
,null
视为比任何值都小
++语文成绩升序排序:++
mysql
mysql> select name,chinese from exam_ret order by chinese;
++语文成绩升序、数学成绩降序、英语成绩降序:++
这个意思是,如果语文成绩一样,按数学降序排序;如果语文、数学成绩一样,按英语降序排序
mysql
mysql> select name, chinese, math, english from exam_ret order by chinese asc, math desc, english desc;
++查询总分,降序排序++
mysql
mysql> select name, chinese+math+english as total from exam_ret order by total desc;
为什么
where
后面无法使用别名,而这里可以使用:在排序之前,是要先有合适的数据
- 先执行
from
,知道在哪个表- 如果有
where
子句,再执行where
,拿到筛选条件- 筛出要的数据
- 筛选出的数据进行排序
order by
在name, chinese+math+english as total
语句后面,所以order by
后面可以跟别名
++查询姓张或者姓王的同学数学成绩,数学成绩降序:++
mysql
mysql> select name, math from exam_ret where name like '张%' or name like '王%' order by math desc;
2.4 筛选分页结果
mysql
mysql> select * from exam_ret limit 5; #从表的开始连续读取5行
mysql> select * from exam_ret limit 3,5; #从指定位置(3, 下标从0开始)开始,连续读取5行
也可也这样使用,更加明确
mysqlmysql> select * from exam_ret limit 4 offset 1; #从1号下标开始, 连续读取4行
对未知的表进行查询,最后加上limit 1
,防止数据过大,导致全表数据库卡死
只用在数据准备好了,才需要显示,limit
的本质功能就是"显示",它的执行阶段会更加靠后
3. update
++修改指定同学成绩:++
mysql
mysql> update exam_ret set english=100 where name='张炎炎';
++多列修改:++
mysql
mysql> update exam_ret set english=21,math=100 where name='张焱焱';
++总分倒数前三的数学加上25分:++
mysql
mysql> update exam_ret set math=math+30 order by chinese+math+english asc limit 3;
++所有同学数学成绩减10分:++
mysql
mysql> update exam_ret set math=math-10;
当没有筛选条件的时候,要谨慎使用
update
,一个误操作,直接修改了全部的数据
4. delete
++删除指定同学的成绩:++
mysql
mysql> delete from exam_ret where name='老八';
++删除整张表的数据:++
删除表结构和删除表的数据不一样!
mysql
delete from t11;
这里删除整张表的数据,并不会将自动增量的值并不会清零 ,如果想将自动增量的值清零,可采用截断表:
mysqlmysql> truncate for_truncate;
delete
和truncate
区别:
delete
会走事务,truncate
不走事务,即truncate
不会将操作痕迹记录在日志当中
由于不走事务,所以truncate
会比delete
稍微快一点truncate
只能对整表操作truncate
会重置auto_increment
项
5. 插入查询结果
mysql
mysql> create table duplicate_table (
-> id int,
-> name varchar(20)
-> );
mysql> insert into duplicate_table values (2024,'aaa');
mysql> insert into duplicate_table values (2024,'aaa');
mysql> insert into duplicate_table values (2025,'bbb');
mysql> insert into duplicate_table values (2025,'bbb');
mysql> insert into duplicate_table values (2026,'ccc');
当表中有重复数据的时候,可采用:
mysql
mysql> select distinct * from duplicate_table;
这样在显示的时候数据已经去重,可是并未影响到表中的数据
如果想得到没有重复数据的表,可以将该表的去重查询结果插入到另一个表当中,然后将原表重命名,最后将新表改为原始表的名字
mysql
mysql> create table no_duplicate_table like duplicate_table;
插入查询结果:
mysql
mysql> insert into no_duplicate_table select distinct * from duplicate_table;
重命名:
mysql
mysql> rename table duplicate_table to old_duplicate_table,
-> no_duplicate_table to duplicate_table;
为什么是
rename
方式进行:将一个文件上传到
Linux
中,在上传的过程中一直在写入,这个过程并不是原子的,所以会上传到一个临时目录下,当然全部上传完毕之后,最后再统一将这个文件move
到指定目录,move
操作的原子的。
rename
也是同理,等一切就绪了,然后统一放入、更新、生效等
6. 聚合函数
函数 | 说明 |
---|---|
COUNT | 返回匹配查询条件的行数。 |
SUM | 返回匹配查询条件的列的总和。 |
AVG | 返回匹配查询条件的列的平均值。 |
MAX | 返回匹配查询条件的列的最大值。 |
MIN | 返回匹配查询条件的列的最小值。 |
6.1 无分组聚合
示例还是采用之前的
exam_ret
表
++统计总共有多少个学生:++
mysql
mysql> select count(*) from exam_ret;
count(6)
并不是指特定的列或条件,它只是一个值,mysql
会将它解释为计算所有非NULL值为6的数量
++统计语文不同成绩个数:++
mysql
mysql> select count(distinct chinese) from exam_ret;
count
是对结果做聚合,就一个数字,所以要在聚合之前去重,再聚合
统计成绩总分:
mysql
mysql> select sum(math) as math_ret from exam_ret;
统计平均分:
mysql
mysql> select avg(english) as english_avg from exam_ret;
++统计不及格人数:++
mysql
mysql> select count(math) as math_fail from exam_ret where math<60;
++最高分和最低分:++
mysql
mysql> select min(chinese) ret from exam_ret;
mysql> select max(chinese) ret from exam_ret;
6.2 分组聚合
分组是对表当中的数据进行分组,然后根据分组再进行聚合统计
导入测试表(来自Oracle 9i):
mysql
mysql> source /path/scott_data.sql;
- dept部门表
- emp员工表
- salgrade工资等级表
++显示每个部门的平均工资和最高工资:++
mysql
mysql> select deptno, max(sal) sal_max, avg(sal) sal_avg from emp group by deptno;
group by column
,指定列名,实际分组是根据该列的不同行数据来进行分组的分组条件
deptno
,组内一定相同,可以被聚合压缩即分组就是把一张表按照条件在逻辑上拆成多个子表,然后对各自子表进行聚合统计
每个部门的每种岗位平均薪资和最低薪资:
mysql
mysql> select deptno, job, avg(sal) sal_avg, min(sal) sal_min from emp group by deptno, job;
一般在
group by
当中出现的具体列名称才可以在select
后面具体出现还有一类就是聚合函数
++平均薪资低于2000的部门和它的平均薪资:++
-
统计各部门平均工资:
mysqlmysql> select deptno, avg(sal) sal_avg from emp group by deptno;
-
having
配合group by
使用,对结果进行过滤:mysqlmysql> select deptno, avg(sal) sal_avg from emp group by deptno having sal_avg<2000;
having
和where
区别:where
是对具体的任意列进行条件筛选;having
对分组聚合之后的结果进行条件筛选
不是只有磁盘上的表结构导入到mysql
,真实存在的表才叫表;中间筛选出来的、最终结果显示的,也是表,逻辑上的表,即可以理解为 mysql
一切皆表。
所以只要能处理好单表的crud
,所有的sql
场景都能够用统一的方式进行!