本篇博客由 CSDN@先搞面包再谈爱 原创,转载请标注清楚,请勿抄袭。
前言
我前面的博客算是把sql中所有的DDL讲完了,下面就来讲讲关于数据操作的语言,也就是DML。主要就是对表中数据做增删查改的操作。
本篇主要对DML中的增和查进行讲解,下一篇会对DML中的删和改进行讲解。
正式开始
四大块:CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除),按照这个顺序来说的话应该是增查改删,不过平时我们说的增删查改比较顺口。就挨个来说。
Create
这个Create和sql中的create不是一个东西,这里说的是insert,其实我前面博客中多多少少都是涉及到insert了,不过没有详细讲,这里就细说一下insert。
相关语法(不用细看):
这种一堆括号的看起来最烦人了,不照着这个讲,多讲点例子你就明白了。
我来建一张学生表(其中所有的东西我前面的博客都是讲过的,我就不再花时间对里面的类型什么的东西进行讲解了,不懂的同学可以看看我前面的博客):
desc:
来插入点数据。
固定的格式,记死:
insert into 表名字 (哪些列,列与列之间逗号分隔) values (对应列数据,也是逗号分隔);
其中的into其实可以省略的,不过个人觉得加上意思表达的更完整一些,也正好和后面要讲的delete from对应。
插入数据的时候可以全列插入,也可以指定列插入,先来说全列插入。
全列插入
有两种写法,一种是在values左边的括号中指明全部的列:
select语句本篇也是会详细讲的,select *应该认识吧,就是查找全部列的数据。
还有一种是省略左侧的括号,不需要写:
这就是全列插入,所有的列都指明了插入。
指定列插入
还是这表:
因为id是自增列,qq也可以为空,所以这里id列和qq列都是可以省略的。
先来省略id插入:
这里因为id是自增的,所以就是3。
再来省略一个qq:
指明了在哪一列插入就要给对应正确的数据,qq默认为null,所以就是null。
多行插入
上面的都是单行插入,插入数据时用逗号分隔就能进行多行插入:
上面是全列插入,可以省略values左侧的()。
再演示一个指定列的:
插入失败就更新
id是自增列,也是主键列,如果插入时出现冲突就无法插入,比如重新插入一个id为3的:
由于 主键 或者 唯一键 对应的值已经存在而导致插入失败。
可以选择性的进行同步更新操作,语法:
INSERT ... ON DUPLICATE KEY UPDATE
column = value [, column = value] ...
insert……就是前面讲的这点。后面的on duplicate key就是键值重复,update就是更新,下一篇会讲的。
演示一下:
这里是因为id=3而冲突了,更新后的数据是右侧的update后面的数据。
注意更新后的数据不能和原表中的数据产生冲突,不然也没法更新:
如果冲突了,更新时所有的列都能改,包括冲突的列:
注意这里用这个条语句的时候其实会有三种情况:
- 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等
- 1 row affected: 表中没有冲突数据,数据被插入
- 2 row affected: 表中有冲突数据,并且数据已经被更新
比如说:
通过 MySQL 函数row_count可以获取上一次操作导致受到影响的数据行数:
替换
就是replace,和insert用起来很像,来个例子:
这里是直接插入了,并没有替换掉。
替换的时候也是有原则的:
- 主键 或者 唯一键 没有冲突,则直接插入;
- 主键 或者 唯一键 如果冲突,则删除后再插入
来个冲突的:
这里是删除了之后再插入的,从id的33变成34就能看出:
Retrieve
查询,其实是select,很简单,但是细节较多。
select语法简介
也是先给张图,不用细看:
先简单介绍一下每个字段的作用,其中都是大写的,我这里就用小写来说。
select决定了查看哪一列,也就是:
distinct是用来去重的,也就是:
from决定了要查看哪张表:
where决定了要筛选哪一行:
order by决定了筛选结果以什么顺序排列:
limit先不说。
这里先把最基本的查询讲了,后面博客再讲进阶版本的,比如多表查询。不过这里基本的查询也够新手学了。
先来建张表:
desc:
插入点数据,方便等会演示select的操作:
开始查询
全列查询
最基本的,select *:
说一下,正常工作了后是不会直接用select*的,因为这些数据库中的数据都是存放在远端的服务器上的,而且数据量都是比较大的,几百上千万条记录都是有可能的,如果select*全部查找,发过来效率比较低,而且select*全部打印出来看着也不方便看,一般都是指定筛选条件进行查找的。
指定列查询
select 列名(如果有多列就用逗号分隔) from 表名;
比如说指定姓名列:
指定姓名和数学成绩列:
打印的结果会按照你指定的顺序来打印:
select后面跟表达式
说一下,select后面是可以跟表达式的,比如说:
还可以跟null:
刚刚那张表也可以这样用:
虽然这里的10没有什么实际意义。
也可以这样:
那既然可以这样加表达式,那也可以这样:
其实就是english和math列的数据进行相加。
那么也可以这样:
等于是总分。
但是上面这样显示起来有点难看,可以用as对这一列进行重命名:
其中单引号和as都是可以不加的:
中间只要有一个空格就行。
也可以对某一列数据进行算数操作:
对结果去重
刚刚的math是有重复数据的:
如果是多列想要去重的话得要多列的数据都相同才会去重,这里我故意插入一个重复的列:
去重和没去重:
上面虽然猪悟能的math和唐三藏的math一样,但是没有去重,因为不是全部都相同。
去掉重复的:
条件查询
就是带上where的select。
加在后面:
select 列名(如果有多列就用逗号分隔) from 表名 where 筛选条件(条件有多个就用逗号分隔);
不过讲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 个)任意字符;_ 表示任意一个字符 |
按个简单说说,等会会根据刚刚建的那张表做相应筛选操作。
>, >=, <, <=,这几个就不说了,就是比较大小的,等会筛选范围的时候会用上。
=,这个和<=>放一块说,注意MySQL中的=是判断等于,不是==。其实就是能不能和null比较的区别,NULL是不能参与运算的,前面博客也说过,MySQL中的NULL和C中的NULL不一样,C中的NULL在数值上和0、'\0’都是一样的,数值上都是0。到那时MySQL的NULL就是NULL,没啥数值一说,不参与任何运算。
=不能用来比较等不等于NULL,不过先演示一下正常数值的比较:
不等于:
用null来比较:
可以看到用=比较怎么比都是null。
如果用<=>比较:
<=>比较是能成功的。而且正常的数据也能比较成:
不过这里只需要记住=就够了,<=>一般也不用。
判断是否为NULL一般用的是is null或者is not null,不会用<=>的。演示一下:
再来说!=和<>,其实二者一样,<>不能比较null不等:
!=就不说了, 一样的。
between……and是比较范围的时候用的,其实和大于小于那些差不多,等会也会有演示。
in是用来判断某个数据是否在所给的数据中,等会也会演示。
LIKE是用来模糊匹配的,等会也会有专门的例子。
逻辑运算符:
运算符 | 说明 |
---|---|
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0) |
上面这三个其实就像C中的&& 、||和!一样,用起来也很像,等会专门有演示的。
查询的示例
下面所有的查询例子都基于刚刚建的那张表:
英语不及格的同学及英语成绩 ( < 60 )
首先,查之前要确定要的是什么,这里要的是同学及英语成绩,也就是要姓名列和英语成绩列,所以select后面就要跟上 name, english,先来找出这些:
然后条件是英语不及格,那么筛选的条件就是where english < 60。所以合起来就是:
很简答,不过多赘述了。
刚开始介绍select语法的时候也说了,select后面跟的影响的是列,from决定了查的是哪张表,where后面跟的影响的是行,这里就能体现出来了。
语文成绩在 [80, 90] 分的同学及语文成绩
首先,要的是同学及语文成绩,那么就是:
筛选的条件是语文成绩在[80,90]这个区间的,那么就是where chinese>=80 and chinese<=90,and就和C中的&&表达的意思一样:
还可以用between……and:
数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
首先要的是姓名和数学成绩:
然后筛选条件是数学为58、59、98、99的,意思是这四个都可以,那么用的就是或,也就是or:
还可以用in:
后者用起来更方便,也更美观。
姓孙的同学 及 孙某同学
这里涉及到了模糊匹配,简单来讲讲。
就是在查找的时候查找条件没有那么完整,只是提供一部分信息,此时就可以用like进行模糊匹配。
这里要找姓孙的和孙某同学,孙某是指孙x,比如说孙权。而姓孙的不仅可以为孙某,还可以为孙某某,比如说孙悟空。所以要搞清楚一件事,姓孙的包含孙某。
首先找所有姓名:
然后筛选,先来姓孙的,后面用%表示匹配任意多个字符:
再来孙某,后面跟一个_表示匹配一个字符:
同时如果想要匹配孙某某,就可以用两个_:
语文成绩好于英语成绩的同学
很简单,比较一下就行,不过这里为了表现出来语文比英语好,把这两列也搞出来,先查出来:
然后筛选:
总分在 200 分以下的同学
先搞出总分:
然后再筛选:
前面说了列能重命名:
那么后面的where子句能不能用这个重命名的总分呢?
答案是不能。这里报错的是where子句中没有总分这一列。
为啥select中能用,where中不能用呢?
这里要搞清楚sql语句的执行顺序才能理解。
举个例子,某公司老板让面试官去某所学校时带着面试的筛选条件选出符合条件的同学。
类比到sql中:
- 先找到某张表(去某所学校)
- 带着where筛选条件(带着面试的筛选条件)
- 选出符合条件的列(选出符合条件的同学)
对应的子句就是:
- from
- where
- select
所以这条语句:
执行的顺序是这样的:
所以where自然就不认识这个总分了。
那么能不能在where对Chinese+math+english重命名呢?
还是不行,报错了。语法不支持,其实也可以理解,老板让你按照TA的要求来,你总不能改老板的要求吧,只能说是选好了之后你自己再按照你的要求进行其他操作。
语文成绩 > 80 并且不姓孙的同学
先找到语文大于80的:
然后加上不姓孙的条件:
孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
先搞清楚上面的话中的意思,如果是孙某同学就行,如果不是孙某那就得总成绩大于200,且语文小于数学,且英语大于80。
先把后面条件多的搞出来:
就一个猪八戒。
再来加上孙某同学:
如果多个条件要作为一个条件来看,那就可以加上括号。
NULL 的查询
刚刚建的这张表没有null值,我来重新建一个表:
简单加点数据:
查id为空的,不能用=:
用<=>:
但一般用的是:
再在这里强调一下空串’',这个在我前面的博客中也是一直说的,插入一个空串:
查找:
排序查找结果
用order by。
SELECT ... FROM 表名 [WHERE ...] #前面讲的
ORDER BY 某一个列名 [ASC|DESC], [...]; # 排序的
其中order by 列名后面用asc就是升序,用desc就是降序。
asc就是ascend,上升的意思。
desc就是descend,下降的意思。
演示一下:
同学及数学成绩,按数学成绩升序显示
不讲了,很简单。
注意order by也有默认顺序,默认是升序:
但是不建议省略,写出来的话看起来更方便。
注意,null比任何数都小,升序在最上面:
降序在最下面:
查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示
三个顺序的要求,意思是前一个如果相等了就看下一个,比如说这里数学相等了就看英语升序的结果,如果英语还是相等的就再看语文升序的结果。
查询同学及总分,由高到低
其实这个相对来说更简单的,但是这里要注意order by可以用重命名的列:
为啥呢?
想要排序不得先有数据,数据都已经筛选出来了不就能进行排序了吗?当然也可以在筛选之前就排序,但是这样不符合常理,相比于先筛选再排序更麻烦,效率更低。
所以这里order by是在select的后面的,故order by算是第四步,select时已经搞别名了,这里order by肯定就能用了。
查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
这个稍微复杂一点,先来查询姓孙的同学或者姓曹的同学数学成绩:
然后加上排序:
分页查看
先不说什么意思,先来给点示例。
要用到limit。
还是这个表:
假如我要查看前三列,怎么做?
后面加个limit 3就可以。
如果我想查看2 ~ 5列,怎么做?
后面加上1,4。为啥是1呢?
讲讲limit的语法。
limit后面可以跟一个数字n,也可以跟一个数字n+逗号+一个数字m。
跟一个数字n的时候是从表开始处连续读取n行,比如limit 3就是连续读取3行。
跟两个数字的时候前一个为开始位置,开始位置的下表是从0开始的,逗号后面的m为步长,意思就是从指定位置n+1行开始连续读取m条记录。
从第2行开始读两条记录:
从第三行开始读一条记录:
从第1行开始读4条记录:
那这里其实是和limit 4等价的:
所以limit后面跟一个数字的时候默认就是从第一行开始读的。
还有一个和逗号很像的offset,不过用起来的顺序和逗号是反过来的。
比如说从第2行开始读取3行:
从第1行开始读取3行:
那这个有什么用处呢?
有些网站的某个网页有很多图片,但是不会直接全部显示出来,而是有上一页和下一页这样的按钮,其实这些按钮转化成sql语句后就是在用limit进行分页。
比如说上面这张表,按照一页3行来看的话就是这样:
也可以这样:
再比如说这里查找总分第一名的同学,先来把总成绩搞出来:
或者是第二名和第三名:
这里其实就是想说一下limit的执行顺序是在order by后面的,你得先排好序了才能将第几名拿出来,可以说是第五步了。
【建议】对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
到这里本篇就讲完了,下一篇说说update、delete、聚合函数、group by等知识。
到此结束。。。