CRUD:Create(创建)、Retrieve(读取)、Update(更新)、Delete(删除)。
Create
into 可以省略。
插入否则更新
由于主键或唯一键冲突而导致插入失败。
可以选择性的进行同步更新操作语法:
INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...

2 rows affected (0.01 sec):表示表中有数据冲突,并且数据已经被更新。
1 row affected (0.00 sec):表示表中没有数据冲突,数据被插入。
0 rows affected (0.00 sec):表示表中有数据冲突,但是冲突的值跟update的值相等。
替换
主键或唯一键没有冲突,则直接插入;如果有冲突,则删除后再插入。
2 rows affected (0.00 sec):表示表中有冲突数据,删除后重新插入。
1 row affected (0.00 sec):表示表中没有冲突数据,直接插入。
可以看到,如果表中有数据冲突,是删除后再插入的。
Retrieve
- 建立一张表结构。
- 插入以下数据。
SELECT列
全列查询
通常情况下使用*进行全列查询。
- 查询的列越多,意味着数据量越大
- 可能影响索引的使用
指定列查询

查询字段为表达式
- 表达式不包含字段。
- 表达式包含一个字段。
- 表达式包含多个字段。
为查询结果指定别名
SELECT column [AS] alias_name [...] FROM table_name;


结果去重
where条件
一列有多行,实际我们可能需要查询符合某些条件的记录。
比较运算符
逻辑运算符
基本比较
- 英语不及格的同学及英语成绩
-
语文成绩在 [80, 90] 分的同学及语文成绩
使用and进行条件连接。

使用between and进行条件连接。
-
数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
使用or条件进行连接。

使用in条件。
-
姓孙的同学 及 孙某同学
模糊匹配 like:
- like % 匹配任意(包含0个)多个字符
- like _ 严格匹配任意一个字符
姓孙的同学。

孙某同学。
-
语文成绩好于英语成绩的同学

-
总分在 200 分以上的同学

注意:别名不能在where条件中使用。因为select的查询顺序是先查询表再看限制条件再筛选字段。

-
语文成绩 > 80 并且不姓孙的同学

-
孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80

有如下表结构。
- 查询名字为空的同学。
- 查询名字不为空的同学。
- 查询名字等于空串的同学。
结果排序
- ASC:升序,从小到大
- DESC:降序,从大到小
- 默认为ASC
SELECT ... FROM table_name [WHERE ...]
ORDER BY column [ASC|DESC], [...];
注意:没有 ORDER BY 子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序
- 同学及数学成绩,按数学成绩升序显示
order by默认为升序。
- 同学及数学成绩,按数学成绩降序显示
-
查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示
意思就是,如果数学成绩相同,则英语成绩按升序排序;如果数学、英语成绩都相同,则语文成绩按升序排列。

-
查询同学及总分,由高到低
order by中可以有表达式。

order by中可以使用别名。

这里order by为什么能用别名呢?因为排序一定是先有数据,再排序,所以,select的执行顺序是先要有表结构,再筛选数据,再对数据做排序。
-
查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示

- 查询姓孙的同学或者姓宋的同学的总分,结果按总分由高到低显示

select执行顺序。

筛选分页结果
起始下标为0
从0开始,筛选n条结果
- SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
从s开始,筛选n条结果
- SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s,n;
从s开始,筛选n条结果
- SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n,offset s;


-
按 id 进行分页,每页 3 条记录,分别显示 第 1、2、3 页
- 查询姓孙的同学或者姓宋的同学的总分,结果按总分由高到低显示,并只显示两条记录
limit的本质是“显示”,只有筛选数据的工作全都准备好了,最后才显示。此时,select的执行顺序为:
Update
UPDATE table_name SET column = expr [, column = expr ...]
[WHERE ...] [ORDER BY ...] [LIMIT ...]
-
将孙悟空同学的数学成绩变更为 80 分
-
将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分

-
将总成绩倒数前三的 3 位同学的数学成绩加上 30 分

-
将所有同学的语文成绩更新为原来的 2 倍
更新全表的语句慎用!
Delete
删除数据
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
- 删除孙悟空同学的考试成绩
删除整表数据
注意:删除整表操作要慎用!
- 建立如下表结构。
- 删除整张表中的数据。
注意:只是删除了整张表中的数据,表还存在。
- 再插入一条数据。发现自增id在原值上增长。
delete 删除整表中的数据,并没有删除auto_increment项。
截断表
TRUNCATE [TABLE] table_name
- 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
- 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚
- 会重置 AUTO_INCREMENT 项
- 建立如下表结构并插入数据。

- 截断表。

可以看到影响行数是0,实际并没有对数据进行操作。
截断表,会删除auto_increment项。
- 再插入一条数据。自增id重新在增长。
插入查询结果
INSERT INTO table_name [(column [, column ...])] SELECT ...
例:删除表中的的重复复记录,重复的数据只能有一份。
- 创建表结构并插入数据。
如何去掉重复的数据?
查询的时候使用distinct确实可以查到去重之后的结果,但是原表数据没有更改。也不能使用delete 加where限制,会把相同的数据全部删除完。可以这样做:
- 创建一张空表no_duplicate_table,结构和duplicate_table一样。
- 将duplicate_table去重之后的数据插入到no_duplicate_table

-
通过重命名表,实现原子的去重操作。将no_duplicate_table重命名为duplicate_tabe,将duplicate_table重命名为其他名字
聚合函数
-
统计班级共有多少同学
使用*做统计,不受null的影响。


使用表达式做统计。

- 统计数学成绩分数个数
统计的是全部数学成绩的个数。不符合题意。
统计的是去重之后的数学成绩的个数。符合题意。
- 统计数学成绩的总分。
- 统计数学成绩小于100分的分数总分。
- 统计平均总分。
- 统计数学成绩的平均分。
-
返回英语最高分。
- 返回 > 70 分以上的数学最低分。
一定要可聚合,也就是有多个数据才能聚合。
group by子句的使用
select column1, column2, .. from table group by column;

- 如何显示每个部门的平均工资和最高工资
select deptno,avg(sal),max(sal) from EMP group by deptno;
- 显示每个部门的每种岗位的平均工资和最低工资
select avg(sal),min(sal),job, deptno from EMP group by deptno, job;
-
显示平均工资低于2000的部门和它的平均工资
- 统计各个部门的平均工资
select avg(sal) from EMP group by deptno;
- having和group by配合使用,对group by结果进行过滤
select avg(sal) as myavg from EMP group by deptno having myavg<2000;
having经常和group by搭配使用,作用是对分组进行筛选,作用有些像where。区别是什么?条件筛选的阶段不同。
