前言
ok,本篇也是到了我们mysql经典的表增删查改环节啦,这一部分属于mysql的基本对表的操作,也是最常使用到的sql语句,是一定要熟练掌握的!! 本篇先讲插入和查找操作
CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除)
一、插入
语法:
sql
INSERT [INTO] table_name
[(column [, column] ...)] #列字段
VALUES (value_list) [, (value_list)] ... #列字段的内容
value_list: value, [, value] ...
案例:
sql
-- 创建一张学生表
CREATE TABLE students (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
sn INT NOT NULL UNIQUE COMMENT '学号',
name VARCHAR(20) NOT NULL,
qq VARCHAR(20)
);
单行数据 - 全列插入 + 指定列插入
-
指定列插入列字段和列字段的内容一定要一一匹配
sqlinsert into students (sn,name,qq) values(01,'张三',2134); -
全列插入全列插入有两种方式,一个是省略 values 左侧字段名,一个是都指定
sqlinsert into students values(2,02,'李四',2135); insert into students (id,sn,name,qq) values(3,03,'王五',2136);

多行数据 - 全列插入 + 指定列插入
-
指定列多行插入
sqlinsert into students (sn,name,qq) values(04,'赵六',2137),(05,'田七',2138); -
全列多行插入
sqlinsert into students values(6,06,'李华',2139),(7,07,'王明',2140);

更新
由于主键或者唯一键对应的值已经存在而导致插入失败。
但我就是想让它先确认是不是在数据库中存在,不存在就插入,存在不要拦我然后执行后面的修改语句
sql
INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...
如果不存在就插入,存在发生主键或者唯一键冲突不要报错,接着执行后面的修改语句。
sql
insert into students values (14, 111, '周瑜', '56321') on duplicate key update sn=111, name='周瑜', qq=56321;
注意更新的值不能和其他的主键和唯一键冲突,否则不能更新。
-
0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
-
1 row affected: 表中没有冲突数据,数据被插入
-
2 row affected: 表中有冲突数据,并且数据已经被更新

替换
和上面的更新操作其实作用差不多
-
主键或者唯一键没有冲突,则直接插入
-
如果冲突,则删除后再插入
sql
REPLACE INTO students (sn, name, qq) values (8, '杨玉环', '21844');
-
1 row affected: 表中没有冲突数据,数据被插入
-
2 row affected: 表中有冲突数据,删除后重新插入

因为 id 是自增的,刚才sn唯一键没有冲突数据时插入杨玉环的那行时id是8,现在唯一键有冲突时是先删除了冲突的那行再重新插入了西施这行,所以id此时自增到9
二、查找
使用的最多的sql语句
语法:
sql
SELECT
[DISTINCT] {* | {column [, column] ...}
[FROM table_name] # 从那个表筛选
[WHERE ...] # 筛选条件
[ORDER BY column [ASC | DESC], ...] # 对筛选结果排序
LIMIT ... # 限定筛选出来的条数
-
distinct:对内容进行去重
-
*:全列查询
-
column,column...:指定列查询
案例:
sql
-- 创建表结构
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列
- 全列查询通常情况下不建议使用 * 进行全列查询,因为查询的列越多,意味着需要传输的数据量越大;可能会影响到索引的使用。
至于什么是索引,我们后面再说
sql
select * from exam_result;
- 指定列查询指定列的顺序不需要按定义表的顺序来
sql
select id, name, math from exam_result;

-
查询字段为 表达式select 非常特殊,后面可以跟 select 自带的子句,筛选条件等,也可以跟表达式
-
为查询结果指定别名语法:
sql
SELECT column [AS] alias_name [...] FROM table_name;
当然了,可带 as,可不带
结果去重
sql
select distinct math from exam_result;
结合一下如果今天我们需要将表中math去重并指定其别名为'数学'之后查找出来,那么就是:
sql
select distinct math as'数学' from exam_result;

where条件
-
刚刚是对表的整体信息做筛选,但是实际在做查询的时候一定有筛选条件。
-
按条件筛选影响的是未来显示出来信息的条目数或者说是行数,以前是按列位单位把全部行都拿出来了。
-
如果一列想拿那些行由where条件来决定。
where 是筛选子句,后面可以跟特定的比较运算符来决策我们应该如何进行筛选,就有点像 C/C++ 里面的if语句,根据后面条件进行判断
所以也就注定了我们的mysql也有其对应的一系列比较运算符:

还有逻辑运算符:

案例:
- 英语不及格的同学及英语成绩 ( < 60 )
sql
select name,english from exam_result where english<60;
- 语文成绩在 [80, 90] 分的同学及语文成绩使用 AND 和 BETWEEN... AND... 进行条件连接
sql
select name,chinese from exam_result where chinese>=80 and chinese<=90;
select name,chinese from exam_result where chinese between 80 and 90;

- 数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩使用 OR 和 IN 进行条件连接,满足任意一个就为真
sql
select name,math from exam_result where math=58 or math=59 or math=98 or math=99;
select name,math from exam_result where math in(58,59,98,99);

- 姓李的同学或者说李某同学,这个时候我们就可以用 LIKE 模糊匹配% 匹配任意多个(包括 0 个)任意字符注意 MySQL 可以用 ' ' 或者 " " 表示字符串
sql
select name from exam_result where name like '李%'; # 不严格匹配
select name from exam_result where name like '李_'; # 严格匹配一个任意字符
由于前面我们李姓的同学名字都是二字的,因此这里我们先新增一行三字李姓信息来呈现%和_的区别

- 语文成绩好于英语成绩的同学
sql
select name,chinese,english from exam_result where chinese>english;

- 查询出总分在 200 分以下的同学
sql
select name chinese+math+english from exam_result where chinese+math+english<200;

这里我们思考一个问题,我们可以看到 where 后面也有跟表达式,曾经不是说过可以对列进行重命名吗,那 where 后面还用写这么一大堆吗?我们可不可以先用as先取别名然后在where后面直接使用这个别名呢?

可以看到是不行的,为什么?
答:问题就出在SQL语句的执行顺序上!
我们一定是先执行 from , 再执行 where ,然后再执行 select 。
筛选后再执行,从 from 中带着 where 去 select 中筛选
原因:只把小于 where 的相加后再打印,更节省空间
那么也就是说执行where后的语句时,是还没有执行前面的取别名的,因此这个total此时没有被定义过,因此报错
所以不可以在 where 中使用重命名
当然,也不可以直接在where后面使用别名,然后在select后使用这个别名

我们可能会疑惑,欸,刚刚不是说select在where后执行吗,那这个total应该是已经定义了呀,为啥不行,我们会出现这种疑惑是因为我们没有搞懂取别名的本质是快要显示的这个临门一脚的时候才能使用的,因为本质上这个取别名是单纯在数据已经筛选出来时修改一下显示的名称,因此取别名操作是只能跟在select后的!!
- 语文成绩 > 80 并且不姓李的同学
这其实就是考验我们 AND 与 NOT 的使用
sql
select name,chinese from exam_result where chinese>80 and name not like'李%';

- 李某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
sql
select name, chinese, math, english, chinese + math + english as total
from exam_result
where name like '李_' or (chinese + math + english > 200 and chinese < math and english > 80);

NULL 的查询
sql
select name from exam_result where name is null;
select name from exam_result where name is not null;

order by排序
语法:
sql
SELECT ... FROM table_name [WHERE ...]
ORDER BY column [ASC|DESC], [...];
-
ASC 为升序(从小到大)(ascending)
-
DESC 为降序(从大到小)(descding)
-
默认为 ASC
-
NULL 视为比任何值都小,升序出现在最上面,降序出现在最下面
注意:没有 ORDER BY 子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序
这句话的核心意思是:不写
ORDER BY的 SQL 查询,返回结果的行顺序是 "随机不可控" 的,绝对不能认为结果会按固定顺序(比如插入顺序、ID 顺序)返回
案例:
- 查询同学数学成绩,按数学成绩升序显示
sql
select name,math from exam_result order by math asc;

- 查询同学各门成绩,依次按语文升序,数学升序,英语降序的方式显示
sql
select name,chinese,math,english from exam_result
order by chinese,math,english desc;

这里的意思是我们首先就是按语文成绩进行升序排序,如果语文成绩相同就按数学成绩升序排序,如果数学成绩也相同就按英语成绩进行降序排序,只是这里我们语文成绩没有相同的就体现不出来效果
- 查询同学的总分,从高到低进行排序
sql
select name,chinese+math+english as total from exam_result order by total desc;

欸,这里我们是成功在from后面的语句中使用了别名,成功的理由如下:
你要对表结构的数据进行排序,一定是得先有数据!
有人可能说不是表结构不就天然有数据吗我直接把表结构数据全排完,然后在选行不行。但你会愿意这样浪费时间处理数据排序吗?
因为你没有筛选,在排序的时候一定有大批数据其实是不需要排序的,而对这些数据排序本身就是浪费空间和 时间,mysql没有这么笨!
所以会先筛选 select 再排序 order by
也就是说在order by执行时这个total已经在select执行时被定义啦
limit筛选
什么是分页呢?
-
如果一个表中数据量太大,这个时候如果全列查询就有一大堆,这样不便于查看分析
-
有时候我们不想一次显示这么多,因此我们就可以对结果进行 LIMIT 分页。
limit 本身没有筛选功能,只是 按照它后面跟的数字 把要显示的结果按照起始位置和步长 给我们显示多条记录。
语法:
sql
-- 起始下标为 0
-- 从 s 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n
-- 从 0 开始,筛选 n 条结果
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
-- 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
-
默认从 0 下标开始,筛选多条记录。
-
limit 分页读取的执行顺序,是在最后的
-
也可以指定下标开始筛选后面跟的是步长。从指定位置开始,连续读取多条记录
案例:
sql
select * from exam_result limit 3 offset 2;

表示从第三行(下标为2)开始筛选3条结果
与我们的排序结合一下筛选案例:
