MySQL的查询主要是对表的增删查改,也叫CURD。Create(创建), Retrieve(读取),Update(更新),Delete(删除)
1.Create
首先说明,这个create并不是创建一张表或者一个数据库,这里是指增加数据的意思,向表中增加数据。
语法:
INSERT [INTO] table_name
(column \[, column\] ...)
VALUES (value_list) [, (value_list)] ...
value_list: value, [, value] ...
为了说明这个语法,先创建一张学生表:

首先,按指定列插入 :
在插入数据时,可以指定好要具体赋值的属性,没有具体说明的会按照默认值,当然not null的限制可能要求你必须给具体的值。

发现:按照指定列插入成功!如果value_list中有其他数据,即使表中有这个列,没有指定,依然不能插入;插入顺序也有要求,必须按照指定列的顺序
全列插入 :不用指定列,value_list中必须按照定义表时列的顺序和数量。

以上两种插入主要在意的是一条数据要怎么插入进表中;我们发现它们都只能一次插入一条数据,它们也被叫做单行数据插入。这样一条一条插入效率比较低,我们还可以多行插入。
语法上,形式依旧是全列或者指定列,只不过在values_list中,写完一条数据,用逗号加上下一条数据。

插入冲突:
在插入数据时,可能因为主键和唯一性的冲突,导致插入失败,那么怎么面对这种冲突呢?

这冲突一般分为两种,一种是确实是你输入的数据有误,只需你正确输入就行了。另外一种是数据无误,但是和已有的数据冲突,这时候就取决于插入时是否更新。也就是把原来的数据更新。
语法:
INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...

我们可以看到有2行被影响,这表明数据冲突,并且更新。对于这个结果,一般有三种情况:
-- 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
-- 1 row affected: 表中没有冲突数据,数据被插入
-- 2 row affected: 表中有冲突数据,并且数据已经被更新
还可以通过MySQL函数获取影响的数据行数
SELECT ROW_COUNT();

这个插入否则更新的命令,一般用于对冲突的数据进行修改;比如例子中冲突的是'sn',update的是name,sn,可以看到qq,id并没有改变,也就是update后的数据就是会覆盖原来的,具体要更新哪些数据就具体情况具体分析了!
另外一种方案,替换!
主键 或者 唯一键 没有冲突,则直接插入
主键 或者 唯一键 如果冲突,则删除后再插入

结果一般分为两种:
1 row affected: 表中没有冲突数据,数据被插入
2 row affected: 表中有冲突数据,删除后重新插入
2.Retrieve
retrieve意思是查询,检索。查询数据是使用频率最高的操作。
语法:
SELECT
DISTINCT\] {\* \| {column \[, column\] ...} \[FROM table_name
WHERE ...
ORDER BY column \[ASC \| DESC\], ...
LIMIT ...
我们先创建一个案例:
创建表
CREATE TABLE exam_result (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL COMMENT '同学姓名',
chinese float DEFAULT 0.0 COMMENT '语文成绩',
math float DEFAULT 0.0 COMMENT '数学成绩',
english float DEFAULT 0.0 COMMENT '英语成绩'
);
插入数据
INSERT INTO exam_result (name, chinese, math, english) VALUES
('唐三藏', 67, 98, 56),
('孙悟空', 87, 78, 77),
('猪悟能', 88, 98, 90),
('曹孟德', 82, 84, 67),
('刘玄德', 55, 85, 45),
('孙权', 70, 73, 78),
('宋公明', 75, 65, 30);

SELECT 列
全列查询:
通常情况下不建议使用 * 进行全列查询
- 查询的列越多,意味着需要传输的数据量越大;
- 可能会影响到索引的使用。
seletc * from 表名

指定列查询
指定列的顺序不需要按定义表的顺序来

查询字段为表达式
可以将表达式当作列来查询,这个表达式可以含有字段也可以不含有

为查询结果指定别名
语法:
SELECT column [AS] alias_name [...] FROM table_name;

为查询结果去重
在select后面加上distinct

有重复成绩98,进行去重:

WHERE 条件
where是一个比较重要的语法,它的作用就是根据条件对去筛选结果,类似于if判断类的语句。
判断通常需要比较,where有两种比较:比较运算符和逻辑运算符
比较运算符:

案例:
一些基本比较
查询英语成绩不及格的同学

语文成绩在70到90之间的同学

可以用逻辑运算符AND,也可以用between and
数学成绩是58或者59或者98或者99分的同学及数学成绩
拿到一个需求,首先要看结果是哪些列,这里对应的是同学和同学的数学成绩,同学就对应姓名。
再来看条件,全是或者,所有条件用OR连接

这样有点冗长,像这样在多个条件中匹配可以用IN

姓孙的同学 及 孙某同学
姓孙的同学意思是只要姓为孙就行,孙某意思是姓孙并且名只有一个字,总和来看就是找出所有姓孙的同学,名字是不清晰的,模糊的,用到模糊匹配

语文成绩好于英语成绩的同学
用语文成绩与英语成绩比较,支持运算符两侧都是字段。

但这样信息不太明显,不能体现这是按照条件进行筛选后的结果,最好这样写:

总分在200分以下的同学
总分是指所有成绩的总和,表中没有这个字段,说明要用别名

我们发现,where识别不了总分,说明where语句里不能使用别名!
这是为什么,先想想查询的过程,有两种流程,一是把需要的字段全部列出来,在按条件进行筛选;另一个是直接用条件去筛,把结果列出来。MySQL是讲究效率的,所以是先进行筛选。这样我们可以得出一个语句执行的优选顺序:

因此正确的语句是:

语文成绩 > 80 并且不姓孙的同学
首先要的字段是同学,也就是名字,最好带上语文成绩;两个条件是 "并且"的关系,用AND,不姓孙,名字依旧是模糊的,但是这次具有否定性,用 NOT LIKE。

孙某同学,否则要求总成绩 > 200 并且语文成绩 < 数学成绩并且英语成绩 > 80
首先,名字是孙某的同学符合条件,否则......,这个否则其实是或者的作用。后面一串条件可以看作一个条件,在MySQL中,可以用括号把条件括起来,以便于阅读。

NULL 的查询
查询QQ号已知的同学(student表)

对于各种比较运算符,如果NULL不安全,比较是没有意义的

需要用到NULL安全的比较运算符,但最好使用IS NULL 或者 IS NOT NULL,因为这样更利于阅读

结果排序
结果排序,顾名思义就是对查询结果按照升序或者降序排列,没有对结果进行排序,,其顺序是未定义的,可能就是插入数据时的顺序,这个顺序没有说明意义,不能依赖这个顺序。
语法:
SELECT...FROM table_name[WHERE...]
ORDER BY column[ASC|DESC],[...];
ASC为升序(从小到大)
DESC为降序(从大到小)
默认为ASC
案例:
同学及数学成绩,按数学成绩升序显示

同学及 qq 号,按 qq 号排序显示

我们发现NULL排在最前面,NULL是最小吗?降序试试

NULL视为比任何值都小
查询同学各门成绩,依次按数学降序,英语升序,语文升序的方式显示
这样的排序有多个条件,众所周知,条件不一样顺序几乎不一样,那么按照那个条件为准?其实这里的次序就是优先级,按照数学降序,如果数学相同怎么办?按照英语升序,以此类推。

查询同学及总分,由高到低
这个查询其实挺简单,但是总分这里有涉及到别名,前文说到where语句中不可以使用别名,那么order by呢?

order by是可以用别名的。为什么?很简单的一个逻辑,没有数据,无法排序,必须先把合适的数据找到了,才能进行排序!
查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
结果应该是姓名和数学成绩,条件是姓孙或者姓曹的同学,最后按照数学成绩降序排序

筛选分页结果
分页查询,对查询结果进行数量上的限制,可以优化性能并提升用户体验。
语法:
起始下标为 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;
使用场景:对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
按id进行分页,每页3条记录,分别显示 第1、2、3页

首先是选择一个字段进行分页,然后决定怎么分,从哪里查询。比如这里按id分页,每页3条,那么就是每3条就是一页,0-2第一页,3-5第二页。

不足三条也算一页。
3.Update
update是更新的意思,对应表的修改,对数据进行修改。
语法:
UPDATE table_name SET column = expr [, column = expr ...]
WHERE ...\] \[ORDER BY ...\] \[LIMIT ...
对查询到的结果进行列值更新
案例:
将孙悟空同学的数学成绩变更为80分
先看一下原来的数据

数据更新

观察一下更新语句和查询语句,我们发现,更新语句需要的条件跟查询一样,其实更新也能近似地看成查询,因为更新数据,需要精确到哪个数据,本身就有查询的部分。
将曹孟德同学的数学成绩变更为60分,语文成绩变更为70分
这里一次改变多个数据,但是查询逻辑很简单。
原数据:

更新:

将总成绩倒数前三的3位同学的数学成绩加上30分
首先看一些原数据

现在加分,注意MySQL中不支持 math+=30这样的语法,而且,总分加了,倒数前三结果应该会改变。

将所有同学的语文成绩更新为原来的2倍
如果我们不加条件,不排序,那么更新操作将是对全表进行更新,更新全表的语句慎用!
先看原数据

更新

4.Delete
delete的意思是删除,顾名思义就是对表中的数据进行删除,一般数据是很重要的,进行这个操作要谨慎!
语法:
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
案例:
删除孙悟空同学的考试成绩
先看一下原数据

进行删除

删除整张表数据
注意:删除整表操作要慎用!
首先准备一张用于删除的表
CREATE TABLE for_delete (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);

插入几条数据

然后对整张表数据进行删除

再插入一条数据

发现自增长没有"清零",delete并不影响自增长的历史。如果你想删除表数据并且"清零"自增长这样的属性,需要用到截断表
截断表
语法:TRUNCATE [TABLE] table_name
注意:这个操作慎用
- 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
- 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚。
- 会重置 AUTO_INCREMENT 项
先准备一张表
CREATE TABLE for_truncate (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
插入几条数据

截断表

注意影响行数是 0,所以实际上没有对数据真正操作
再查询一下结果

插入查询结果
语法:
INSERT INTO table_name [(column [, column ...])] SELECT ...
从语法中我们可以看到,insert into 后面 是 select,把查询结果当作数据进行插入,从中我们可以得出这两种表结构上肯定要相同;另外,查询结果也是一张表,虽然它并没有真正存储在硬盘上,但在逻辑上它确确实实存在。
案例:删除表中的的重复复记录,重复的数据只能有一份
先创建这样的表再插入数据
CREATE TABLE duplicate_table (id int, name varchar(20));
INSERT INTO duplicate_table VALUES
(100, 'aaa'),
(100, 'aaa'),
(200, 'bbb'),
(200, 'bbb'),
(200, 'bbb'),
(300, 'ccc');

去重的思路:
创建一张空表 no_duplicate_table,结构和 duplicate_table 一样
将duplicate_table去重的数据插入到no_duplicate_table
通过重命名表,实现原子的去重操作


5.聚合函数

案例:
统计班级共有多少同学

统计班级收集的qq号有多少

这就是count的用法,而且我们还发现NULL不计入结果
统计本次考试的数学成绩分数个数

统计出个数,但是这样统计是不去重的,去重类似select加上distinct

加在括号内,是去重后统计,而不是统计后再去重。
统计数学成绩总分

不及格 < 60 的总分,如果没有结果,返回 NULL

统计平均总分
这里也是用到别名

返回英语最高分

返回**> 70****分以上的数学最低分**

以上就是一些聚合函数的用法。
6.group by****子句的使用
group by是分组的意思,在MySQL中是对表进行分组,这个分组其实是一种"分表",将表按照一个字段进行"重构",当然表本身是没有说明变化的,只是在逻辑上这种表的结果改变了。
语法:select column1, column2, .. from table group by column;
案例:
准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)
EMP员工表
DEPT部门表
SALGRADE工资等级表
这个表网络上应该可以检索下载到



显示每个部门的平均工资和最高工资
首先也是最重要的,每个部门,怎么按部门分,deptno是部门号,按照部门号分就可以分成不同的部门了。

显示每个部门的每种岗位的平均工资和最低工资
首先按照每个部门分组,也就是按部门号分组,员工现在被部门号分成了几组,而每个部门又有不同的工种也就是岗位,所以可以按岗位再分,也就是按照job分组。

为了更好理解,可以把分组信息带上,deptno和job。
显示平均工资低于2000的部门和它的平均工资
这个有点复杂,但我们可以拆成几步来,先看平均工资,按照部门分组统计平均工资

再条件筛选,平均工资低于两千

这里用到了having,作用是像where一样进行筛选,having经常和group by搭配使用,作用是对分组进行筛选。
它们两个的区别:where在group by之前就进行筛选了,having是分组再进行筛选。where 中不能直接使用聚合函数,having可以。
谢谢浏览!!!