文章目录
- 一、新增数据
-
- 1.1、单行全列插入
-
- [1.1.1、弱类型和强类型 静态类型和动态类型 ==(拓展)==](#1.1.1、弱类型和强类型 静态类型和动态类型 ==(拓展)==)
- 1.2、单行指定列插入
- 1.3、多行插入
- 1.4、插入查询结果
- [二、select 查询](#二、select 查询)
-
- 2.1、整表查询(危险操作)
- 2.2、指定列查询
- 2.3、查询时带有表达式
- 2.4、指定别名
- 2.5、查询结果去重
- [2.6、where 语句 条件查询](#2.6、where 语句 条件查询)
-
- 2.6.1、比较运算符
- 2.6.2、逻辑运算符
-
- [2.6.2.1、关于null (拓展)](#2.6.2.1、关于null (拓展))
- [2.6.2.2、关于 别名在where 语句中使用(拓展)](#2.6.2.2、关于 别名在where 语句中使用(拓展))
- 2.6.3、范围查询
- [2.6.4、模糊查询 like 搭配通配符](#2.6.4、模糊查询 like 搭配通配符)
- [2.6.5、null 的条件语句](#2.6.5、null 的条件语句)
- [3、order by 排序](#3、order by 排序)
- 4、分页查询
- [5、聚合查询 (聚合函数)](#5、聚合查询 (聚合函数))
- [6、group by 分组](#6、group by 分组)
-
- [6.1、having 子句](#6.1、having 子句)
- 7、内置函数
- [三、update 修改操作(危险操作)](#三、update 修改操作(危险操作))
- [四、delete 删除操作](#四、delete 删除操作)
-
- [4.1、截断表、truncate 语句](#4.1、截断表、truncate 语句)
一、新增数据
- 由上面我们知道,我们已经创建好库还有创建好表,那么我们得往表里添加数据吧
1.1、单行全列插入
sql
insert into 表名 values(数据 ,数据....)
- 往表里添加数据用 insert into ... values()
- 这里添加的数据要和表里的列的类型一 一对应
- 如下所示
现有一个 student 表,里面的结构如下
- 现在要把 学号为 1 ,名字为张三,性别为男这条 数据插入表中
sql
insert into student values(1,'张三','男');
插入的数据和表中的列的类型一一对应,1 对 int , 张三 对 varchar
注意 SQL中的字符和字符串都用 '' 表示
- 效果 如下

1.1.1、弱类型和强类型 静态类型和动态类型 (拓展)
- 在SQL中,如果在上面的表中插入
sql
insert into student values('100','张三','男');
- 我们知道,插入的数据 要和表列的类型要一一对应,但是现在 第一个数据是字符串类型,这种情况依然能插入成功。原因是SQL是弱类型编程语言。
- SQL中存在类型转换,即使你 values 后面写的值,类型上不是严格匹配,但是 SQL 会尽量尝试进行转换,如果转换失败,会报错。如果转换成功,就可以插入
- 那什么是强类型,什么是弱类型呢?
- 类型和类型之间,分界越明显,类型越强
- 语言越不支持隐式类型转换,类型就越强
- 语言越支持隐式类型转换,类型就越弱
- 那什么是静态类型,什么是动态类型?
- 静态动态类型 和 强弱类型无关
- 主要的区别就是 变量在程序运行过程中,类型是否能改变
- 会 ,那就是动态类型
- 不会,那就是静态类型
1.2、单行指定列插入
sql
insert into 表名(指定列,指定列)values(数据,数据)
- 指定列,一定是表中的列
- 数据的个数 一定和指定列的个数 一样
- 并且数据的类型要和指定 列的数据类型一样
- 现在我要在 student 这个表中插入一个名字为李四,性别为 男 的数据
sql
insert into student(name,genter) values('李四','男');
- 效果如下

此时没数据插入的列,就显示为null
1.3、多行插入
sql
insert into 表名 values (数据,数据),(数据,数据),(数据,数据 )......;
- 意思就是一次性插入多条数据
- 数据 的类型和个数必须要和表内的列数和类型一一对应
- 我现在要插入 3王五女,4赵六男,5 田七男 这三条数据到student表中
sql
insert into student values(3,'王五','女'),(4,'赵六','男'),(5,'田七','男');
- 效果如下

- 那单行插入和多行插入有什么区别呢?
- 如果上面的操作是单行操作,就是一次插入一条,分三次
- 我们知道 MySQL 是客户端- 服务器,这样的结构,是通过网络通信来进行信息交互的。那么分三次插入,实际上是进行了三次网络通信。那么如果是多行插入,实际上是只进行了一次网络通信。所以是开销的问题
- 如果是一次性插入大量的数据,那就另当别论
1.4、插入查询结果
sql
insert into 表名 select 列名 from 表名 ....
- 把查询的结果,插到另一个表中
- 后面查询出来的列数和类型要和前面插入的表的结构匹配
- 列的名字是不需要匹配的
- 我要把 student 这个表的数据插到 stu 这个表中
sql
insert into stu select * from student;
- 效果如下

二、select 查询
- 查询得出供我们看的表,其实是临时表,也就是说,在临时表修改了数据,并没有修改硬盘里存的数据
2.1、整表查询(危险操作)
sql
select * from 表名
- 查询用 select... from
- ' * ' ,表示通配符 ,表示 这张表的列的全部 类型
- 我要查询 student 这张表
- 效果如下

- 为什么说是危险操作?
- 这个整表查询 ,会把表中的数据全部查询出来。在公司中这张表的数据会非常多,涉及到大量的硬盘访问和网络询问
- 这就会导致一个问题,会瞬间把数据库所在的机器的硬盘和网络宽带吃满。那么用户端就访问不到。卡顿死机等
2.2、指定列查询
sql
select 列名,列名 from 表名;
- 我要查询 student 这张表中的,name 这一列
sql
select name from student;
- 效果如下

2.3、查询时带有表达式
sql
select [列名],表达式 from 表名
- 一边查一边进行一些计算,简单的统计
- 主要是一行中的列和列之间的计算
- 我有一张exam 表,里面的数据如下

- 我要计算语文 加上数学加上英语的总和
sql
select name,chinese+math+english from exam;
- 效果如下

- 这里给我们看的是临时表,这里的操作也是在临时表上操作
- 临时表上的操作并不会影响到数据库服务器硬盘中的原始数据
- 看上面列的名称,这里我们是不是可以理解为总分的成绩。看上面那个表达式是不是很别扭,那我们怎么操作才能改名呢?就是下面那个指定别名
2.4、指定别名
sql
select 表达式 as 别名 from exam;
- 指定别名用 as ,此处的as可以省略,只需用一个空格(不建议省略)
- 我要把 Chinese + math+english 改为 总分
sql
select name,chinese+math+english as '总分' from exam;
- 效果如下

2.5、查询结果去重
sql
select distinct 列名 from 表名;
- 查询结果去重,要使用 distinct
- 把多个相同的值,合并成一个
- 当指多个列去重的时候,要求多个列都是相同的值,才能去重
2.6、where 语句 条件查询
sql
select 列名... from 表名 where 表达式;
- 条件查询使用的是 where
- 根据查询的条件,对于要查询的行,进行筛选
- 条件成立,这一行作为查询结果。如果不成立,这一行就跳过
- 我要查询英语不及格的同学和英语成绩
sql
select name,english from exam where english < 60;
- 效果如下

- 本质上,拿着表里的数据,一条一条遍历,一条一条的代入条件
2.6.1、比较运算符
- 大小于运算符
和我们之前学的没什么区别
- = ,等于就有区别。
- 我们学的 Java 等都是 使用 == ,来比较相等,而用 = 这个来表示赋值,SQL 这里赋值和比较相等都用 = (看上下文来判断是哪个)
- 对于比较 null 比较不安全,比如说 null = null ,按正常,这条判断语句应该返回 true ,但是这里就返回 false
- 这里就有了 <=> 这个判断相等
- 这里对于 null <=> null ,这种就能正确的返回 true
2.6.2、逻辑运算符
- 我们知道 Java 和 C 中的逻辑运算符都使用 && || ,这些
- 但是 SQL 中用的是 and or not (与 或 非)
- and 对应与
- or 对应或
- not 对应非
- and 和 or 的优先级
and 的 比 or 优先级更高,所以必要时加上括号
2.6.2.1、关于null (拓展)
- SQL 中把 null 视为 false
- SQL 拿别的值和null 进行运算,结果还是 null 什么意思呢?
比如 上面的 exam 表,我有一个列的 Chinese 值为空,这时 使 Chinese + 10 。 我们正常来理解肯定 chinese 在表中的值为 10。但是实际上 还是 null
2.6.2.2、关于 别名在where 语句中使用(拓展)
- 我要在统计总分在200分以下的同学
sql
select name,chinese+math+english as total from exam where chinese+math+english < 200;
- 在前面定义的别名 total 在后面的条件判断 where 中能否使用呢? 如下代码
sql
select name,chinese+math+english as total from exam where total < 200;
- 按照 Java 中 我们正常的理解逻辑中,这种是没什么问题的
- 但是在SQL中,这段代码是不能运行的
- 原因是别名定义在判断语句之后,就是编译器在执行过程中先执行where语句,发现不知道 total 是什么东东,所以就报错
- 底层运行流程
- 先遍历表
- 取出表的每一行,代入条件 (使用别名)
- 把符合条件的行筛选出来
- 根据 select 后面指定的表达式进行计算 (定义别名)
- 所以就有了 where 后面的条件不能使用别名
- 那既然这样,那我能否在where 后面的条件中定义别名呢?
- 答案:也是不行的
2.6.3、范围查询
2.6.3.1、between
sql
列名 between a0 and a1;
- 用 between ... and... 来表示列中的值是否在 a0 到 a1 这个区间
- 注意这里的区间不同Java(左闭右开),SQL 是 (左闭右闭)
- 我要统计语文成绩在 80,90 的同学 和 语文成绩
sql
select name,chinese from exam where chinese 80 and 90;
- 效果如下

2.6.3.2、in
sql
列名 in ()
- 判断列名的值是否在集合中
- 我要统计 数学成绩是 78 或者 79 或者 98 或者 99 分的同学和数学成绩
sql
select name,math from exam where math in (78,79,98,99);
- 效果如下

2.6.4、模糊查询 like 搭配通配符
sql
列名 like '% / _'
- 使用的是 like
- % ,代表任意个任意字符
- _ ,代表一个任意字符
- 这里的查询 效率一般,所有企业中慎用
- 我要查询所有姓孙的同学
sql
select name from exam where name like '孙%'
- 效果如下

- 我要查询名字为两个的姓孙同学
sql
select name from exam where name like '孙_';
- 效果如下

2.6.5、null 的条件语句
- is null
- is not null
3、order by 排序
sql
select 列名 from 表名 order by 列名 [指定排序规则]
- 排序查询用 order by
- 默认的排序规则是升序(小到大)
- asc 表示 指定升序,默认就是这个
- desc 表示指定降序 (大到小)
- 空值 (null) 视为最小
- 也是针对临时表操作,不会影响硬盘上的原始数据
- 我要查询同学和总分,由高到低排序
sql
select name,chinese+math+english as total order by total desc;
- 效果如下

- order by 是个特殊,他是先执行定义别名,再排序,所以 order by 后面可以使用别名
- 如果 order by 后面跟多个列(即多个列排序),越靠前优先级越高,比如有两个列,先是排序第一个 ,如果第一个有几个排序不出来(就是几个相等的情况 ),那么这几个就按照第二个列来排序
- MySQL 中,没有给你承诺,你就不能依赖这个顺序
什么意思呢,就是插入数据时,一般都有先后顺序。所以我们看到的数据一般都是有序的。但是 MySQL,本质上是无序的我们不能依赖这种有序。要有序就用 order by
- 针对这一列来排序,他是整行移动的(就是整条数据移动,并不是只有列移动)
4、分页查询
sql
select 列名 from 表名 [where 条件] [order by 排序] limit N offset M;
- 分页用 limit ,后面的 N 表示,这一页有多少条数据
- offset 表示 从哪条数据往后 N 条
- 可以使用条件和排序等
- MySQL 的分页查询,就可以用来实现网页中的分页效果
- offset 表示偏移量
- 我要约定一页有三条数据
sql
select * from exam limit 3 offset 0;
- 效果如下

- 从第0条数据往后数3条,不包括第0条数据
- 如果我只有3条数据,如果 offset 后面接的是 4,那么往后数3条就是没有了,在SQL 中最多得到空结果,不会 像数组下标越界那样的情况
- 作用:如果我有100条数据
把所有结果放到一个页面,用户看不过来。也会影响程序效率(因为有开销)。假设我每次只在硬盘中取20条出来,那么最多也就显示20条数据。要取后面的数据 根据 offset 进行修改,那么就完美解决了这个问题
5、聚合查询 (聚合函数)
- 聚合函数是为了进行聚合查询
- 上面的普通查询(指定表达式),是进行 列和列之间的运算,比如一行中的列和列之间
- 聚合查询,是进行行与行之间的运算。比如多行一列之间
- 聚合函数是MySQL 中的库函数
5.1、count
sql
select count(列名) from 表名;
- 使用 select 来引用函数
- 计算这个表中有多少行
- 只有一个参数
- 如果不用 通配符(*),使用的是指定列,那么如果这列中有空,那么不会算进去
- 统计exam 表中 有多少条数据
sql
select count(*) from exam;
- 效果如下

- 这里的count 和 (*) 之间不能有空格。不然编译器以为 定义别名
- 这里的* 如果是指定哪一列。那么这一列如果有空值就不会算上。通配符就会算上
- 这里相当于先执行 select * from exam 。再对结果进行 count
- 这里 ()内只有 一个参数,相当于只能传一列
5.2、sum
sql
select sum(列名) from 表名;
- 返回该列数据的总和。数据要是数字才有意义
- 我要统计所有学生数学成绩的总和
sql
select sum(math) from exam;
- 效果如下

5.3、avg
sql
select avg(列名) from 表名;
- 返回该列数据的平均数。数据要是数字才有意义
- 我要统计英语成绩的平均分
sql
select avg(english) from exam;
- 效果如下

- 即使列是整数,进行求平均值,还是能得到小数的
比如求全部成绩的平均数
- 查询结果,临时表 列的类型 和 原始数据的 列类型 不一定完全一致
5.4、max 和 min
sql
select max(列名) from 表名;
- 返回该列数据的最大值。数据要是数字才有意义
- min 也是一样
6、group by 分组
sql
select 表达式 from 表名 group by 列名;
- 使用的是 group by
- 把表的若干行进行分组,需指定 分组依据
- 指定某列,这个列值相同的行就会分到同一组里
- 会根据分组后的结果进行聚合查询
- 我有一个 emp表

- 我要统计每个角色的人数
sql
select role,count(name) from emp group by role;
- 效果如下

- 前面查询的列要和 后面 group by 的 列对应
6.1、having 子句
sql
select 表达式 from 表名 group by 列名 having 表达式
- 这也是条件语句
- 分组之前指定条件 用 where
- 分组之后指定的条件用 having
- 怎么区分这两种情况 此处主要是看条件,是分组前就能确定还是必须分组之后才能确定的
- 我要统计每个岗位的平均薪资(不包括张三)
sql
select role,avg(salary) from emp where name != '张三' group by role;
- 效果如下

- 这是分组前就能确定的
- 我要统计每个岗位的平均薪资,保留平均薪资 小于 15000 的
sql
select role,avg(salary) from exam group by role having avg(salary) < 15000;
- 效果如下

- 这个条件是分组前做不到的,只能分组后才做
7、内置函数
sql
select 表达式;
- 使用的是 select;
7.1、日期函数
- curdate()
返回当前日期
- curtime()
返回当前时间
- now()
返回当前日期和时间

7.2、字符串处理函数


7.3、数学函数

7.4、其他函数

三、update 修改操作(危险操作)
sql
update 表名 set 列名 = 值 [where 条件] [order by 列名] [ limit N];
- 修改用 update ... set... 这里的 date 很容易写错
- 条件正确,不加条件全部行的这一列全都修改(危险的原由)
例如我要给用户充值10元,如果你没有指定哪个用户,那么所有的用户余额都加10元
- 这里的修改,改的是硬盘中的原始数据,改了就反悔了
- 我要将总成绩倒数前3位同学的数学成绩加上30分
sql
select name,math,chinese+math+english as total from exam order by total limit 3 offset 0;
- 效果如下

先找到总成绩倒数第三的人
- 把总成绩倒数第三的人的数学成绩加30
sql
update exam set math = math + 30 order by chinese+math+english limit 3
- 效果如下

- 这里的 limit 3 后面不能加 offset
- 这里没有条件,本应该改全表的值,我理解改全表应该是临时表这个全表,因为我上面只取了 limit 3 ,行。所有本质上也是改了临时表的全部值
- 这里的加 30 不能写成 +=30,SQL不支持这种写法
- 这里的 = 号就是赋值的意思
四、delete 删除操作
sql
delete from 表名[where 条件] [order by 列名] [limit N]
- 这里的删除用 delete from
- 要通过 where 等的条件子句限定删除哪些内容。如果不写条件就会删除所有数据 最终得到一个空的表
- 这里的删除和上面 drop 表名 这个删除不一样。这里的删除是删除数据,表还在。drop 这个是直接删表,表也不见了
如这里的删除和链表中删除每个val值一样,链表的整体结构还在。drop 删除 就相当于 直接让 list = null;
- 我要删除孙悟空的考试成绩
sql
delete from exam where name = '孙悟空';
- 效果如下

4.1、截断表、truncate 语句
sql
truncate 表名;
- 更快速的 清空表的方式
- delete 的方式删除,本质上是一条一条的删,数据比较多,会删得很慢
