MySQL表的增删改查
大家好,这次给大家带来的是我的新的专栏:数据库,数据库相对来说难度不是那么高,大家只要勤加练习、熟记语法,我相信学好数据库不是什么问题,博主会从0剖析,逐步讲解数据库的知识点,并且会举很多实例。最重要的是,博主不会采用软件,使用最原始的方式 -> 命令行来讲解,这样讲解的好处是逐个语句进行书写,不会造成读者思路跟不上的问题!
👀QQ:162196770
👀微信:PRIDE_Xu_
👀Gitee:https://gitee.com/jialebihaitao
文章目录
1、MySQL表的CRUD
CURD
即为创建(Create)
、读取(Retrieve)
、更新(Update)
和删除(Delete)
。
咱们以后在公司中,如果是一个"后端开发工程师",那么刚入职的大多数的时间都在进行CRUD
2、插入数据
2.1 语法
insert into 表名 values (列的值...);
2.2 注意事项
要求
values
后面的括号中的字段的个数和表头约定的列数以及每个列的类型要匹配比如,在输入
int
类型的id
的时候,必须输入int
类型数据,输入其他类型的数据会报错。但是有的类型,
SQL
可以自动帮我们进行类型转换,但是我们大家尽量不要依赖这种方式在
SQL
中,表示字符串,可以用单引号也可以用双引号 ! 而且不要用中文的标点符号 ! ! !推荐大家使用单引号 , 因为这是大家统一的标准 ! Oracle 当中的字符串就只能用单引号包裹
如果某一列是
datetime
,那么如何进行插入呢
通过指定格式的字符串来插入一个指定时间
最推荐的时间日期的格式 :
YYYY-MM-DD hh:mm:ss
比如:
2022-04-26 09:39:50
通过
now()
函数来插入一个当前的系统时间
insert
语句插入的时候,也可以只插入部分列(某一列或某几列),此时未被输入的其他列将是默认值如果插入中文失败了,请看这篇博客
传送门
insert
也可以依次插入多个行
values
后面的每个()都对应到一行,可以一次性的带有多个(),多个()之间用,
分隔注意:
类似的功能,也可以依次插入两行,分两个
insert
语句插入insert into student values (1,'zhangsan',19,80.3); insert into student values (2,'lisi',25,76.5);
但是一次插入
n
条记录,要比一次插入一条,插入n
次快得多得多!我们可以分析一下原理:
服务器是通过一些复杂的数据结构来组织数据的.
每次的插入操作都是比较耗时的 , 因为需要进行遍历操作找到合适的位置才能进行插入 .
如果是一次插入一条数据 , 分多次插入 , 服务器这边的准备工作就要进行多次 .
如果是一次插入多条数据 , 分成一次插入 , 服务器这边的准备工作只需要做一次就足够了
所以,发送一条指令的速度一定是比多条指令快
3、查找语句
查询语句在SQL
语言至关重要,难度也略高,要努力嗷~
3.1 全列查找
直接把一个表中的所有列和所有行都查询出来
语法:
select * from 表名;
其中:*
叫做通配符,表示一个表的所有列
其实,我们之前也用过了几次这个语句。
我们需要知道的是:
把一个表里面的所有的行和列都查找到,查找出来的结果是一个临时表(即之前介绍的,存放在内存上,不是在硬盘上,结束之后数据就会消失)。
这条语句也算是一个高危操作!我给大家分析一下:
如果在生产环境上执行这个操作,那么就容易产生问题。我们知道,生存环境保存着许多数据,有可能是
TB
级别的,这时候服务器就疯狂地检索数据,而硬盘的读取速度也是有限的。同时也在疯狂地通过网络返回数据,这也会把宽带的带宽占满!一旦服务器的硬盘和网络被占满,此时数据库就无暇应对其他客户端的请求,而且我们之前介绍,生产环境是无时无刻对各种用户提供响应的。所以此时的数据库就啥用没有,谁也用不了了。在公司中,如果出现这种长时间执行且速度慢的操作,会强制把这个SQL
操作给杀死。如果我们真的执行了这样的语句导致服务器卡顿了 , 赶紧按 ctrl + c 终止 SQL 的执行
select
操作,并不会影响到服务器这边硬盘上存储的数据
3.2 指定列查询
只查询自己关注的列
语法:
select 列名,列名... from 表名;
在进行这个操作之前,我们创建一个考试表,里面存放若干数据。
create table exam_result (
id int,
name varchar(50),
chinese double(3,1),
math double(3,1),
english double(3,1)
);
insert into exam_result values
(1,'唐三藏', 67, 98, 56),
(2,'孙悟空', 87.5, 78, 77),
(3,'猪悟能', 88, 98.5, 90),
(4,'曹孟德', 82, 84, 67),
(5,'刘玄德', 55.5, 85, 45),
(6,'孙权', 70, 73, 78.5),
(7,'宋公明', 75, 65, 30);
我们可以只选择查询名字以及语文成绩。
这里在查询的时候,明确告诉数据库要查找的是那些列,数据库就可以有针对性的返回数据了 , 这样就节省了大量的磁盘 IO 和网络带宽了。那么这种方法,相比于全列查找效率就高出很多了。在以后工作中的数据库,十几列都是有可能的。所以全列查找会很浪费时间。所以这种方式使用频率更高。
那么这个操作的查询结果,也只是一个临时表,对于服务器里面的数据没有任何影响。
3.3 指定查询字段为表达式
select 表达式 from 列名;
在查询时候,同时进行一些运算操作(列和列之间)
行与行之间的比较我们之后会讲解
举个栗子:把所有人的语文成绩加十分
查询一下所有同学们的总分
我们要注意的是,之前定义数据表的时候,不是定义的是double(3,1)
吗,这不代表有效数字3位,小数点后面一位吗?那这里都有效数字已经4位了,怎么回事?
临时表中的结果的数据类型不一定和原来的表的数据类型完全一致
临时表会自动适应数据类型,保证计算结果正确。
但是往原表里面插入类似于 106.3 这样的数据就会报错 .
表达式查询还有许多令人迷惑的操作
上述操作,都是针对一个或者多个列进行的运算,也就是针对指定列中的每一行数据进行相同运算(比如唐三藏自己的三科成绩相加,孙悟空自己的三科成绩相加),行和行之间互不影响(唐三藏、孙悟空三科成绩互不干扰)
3.4 查询字段指定别名
select 表达式 as 别名 from 表名;
相当于是给临时表起一个新名字,来避免得到的临时表名字很乱防止混淆
其中,as
关键字可以省略,但是不推荐,因为这有可能会被误认为total
是一个单独的一列(很有可能误看成前面有个逗号)
也可以指定多个别名:
注意:只是将显示的查询结果列名显示为c / e,原表列名还是叫:chinese / english
记住:select 语句是永远都不会进行修改操作的。(因为只负责查询)
假设起别名的时候,别名里面有空格,怎么办?
我们可以用单引号给他扩起来
注意:在所有的数据库当中,字符串统一使用单引号括起来,单引号是标准,双引号在oracle数据库中用不了。但是在mysql
中可以使用。
再次强调:数据库中的字符串都是采用单引号括起来。这是标准的 . 双引号是不标准的
3.5 针对查询结果去重
针对查询的结果,把重复的记录给去掉
我们这时候插入甄嬛,让她的数学成绩也为98.0
。
我们可以看到,本来应该有两个98.0
,通过distinct
关键字,最后只剩下了一个98.0
.
不过,distinct
在工作中使用频率略低。
还需要注意一点:distinct
如果是针对多个列进行去重,那么就需要这多个列的值都相同的情况下才视为重复。
比如:我们又插入了沈眉庄的成绩,他的语文成绩也是
67.0
,数学成绩也是98.0
,这两门成绩跟唐三藏这两科成绩相同。我们再插入一个富察贵人的成绩,让富察贵人只有语文成绩跟唐三藏相同,都为
67.0
。所以,我们可以知道:当
distinct
筛选两条记录时候,只有数学语文成绩都相同,才被筛选掉,只有一科成绩相同是不会被筛选掉的。多条记录同理
3.6 排序
针对查询结果(临时表)进行排序(不会影响到服务器上的原始数据)
语法:
select 要显示的列名... from 表名 order by 列名 asc/desc;
比如:
针对数学成绩进行排序
升序
asc默认不写,也是升序
降序 : desc
这里的 desc 不是之前的 describe ,此处的 desc 是 descending order(降序)
有的数据库里面是带有
NULL
值的,NULL
会被认为成是最小的(即升序排在最前面,降序排在最后面)我们这个时候再插入一个安陵容的成绩,安陵容由于缺考没有成绩
排序也可以指定别名或者表达式来进行排序
order by 可以使用别名操作
NULL
和其他值计算的时候,结果还是NULL
,跟0没有关系排序的时候还可以通过
order by
来指定多个列进行排序。即先根据第一列进行排序,如果第一个列排序结果相同,再根据排序结果相同的两个列进行排序。多个列排序的时候是具有明确优先级的。如果不指定多个列,只制定一个列的话,此时如果结果相同,彼此之间的顺序都是不可预期的。
3.7 条件查询
在select
的后面加上一个where
子句,后面跟上一个具体的筛选条件。
语法:
select 列名 from 表名 where 条件;
那么这里面的条件又是什么呢?
比较运算符:
运算符 | 说明 |
---|---|
>,>=,<,<= | 大于,大于等于,小于,小于等于 |
= | 等于,对于NULL的处理是不安全的 |
<=> | 等于,对于NULL的处理是安全的 |
!=,<> | 不等于 |
between a0 and a1 | 范围匹配,[a0,a1]前闭后闭区间 |
in(option,…) | 判断是不是括号里面任意一个 |
is NULL | 是NULL |
is not NULL | 不是NULL |
like | 模糊匹配 |
注意事项:
=
是比较相等,不是赋值。那么这个语句在处理NULL
的时候效果不太好,NULL=NULL
结果依然是NULL
,会被认为成是假,条件不成立<=>
也是比较相等,用<=>
比较空值(NULL<=>NULL)
,结果是真in(option,...)
意思就是通过后面这个()
给出几个固定的值,判定当前结果是不是在()
里面这几个值当中is NULL
、is not NULL
也是专门和NULL进行比较的- like能进行模糊匹配。
%
表示任意个字符(0个也算);_
表示一个字符;
逻辑运算符:
运算符 | 说明 |
---|---|
and | && |
or | || |
not | ! |
where 子句的筛选 , 可以理解成对于查询到的结果依次进行遍历 , 把对应的查询结果放到筛选条件去比对 , 满足条件的 , 就把这个查询结果放到最终查询结果集里面 . 不满足条件的,直接舍弃掉 , 不作为最终查询结果 . 其实这里面的条件 , 我们就可以类似成 Java 里面的 if 语句 .
接下来举几个栗子:
栗子1:查询英语不及格的同学及他的英语成绩
那么这个
where
语句就会针对查询结果进行筛选。服务器就会遍历表中每一条记录,满足条件就返回给客户端,不符合条件就跳过
栗子2:查询语文成绩大于英语成绩的同学
那么这里面的查询是针对于某个人自己的语文成绩大于英语成绩的同学,不涉及行和行之间的比较。
那么我们要注意一点,大家可能现在已经弄不懂了,select
后面的列跟where
后面的列有啥区别?
select
后面的列是表示要显示什么,where
后面的列表示要进行什么操作
栗子3:查询总分在200分以上的同学
我们可以看到,
chinese+math+english
的方式没有报错,但是起别名的方式竟然报错了!这说明:where 子句是不能使用别名的
栗子4:查询语文成绩大于80分,且英语成绩大于80分的同学
栗子5:查询语文成绩大于80分,或英语成绩大于80分的同学
and
的优先级高于or
,计算的时候先算and
再算or
,在同时使用时,需要使用小括号()
包裹优先执行的部分先看
math > 70 and english > 70
的人,然后发现前面是个or
,代表要不就是语文大于80的人,要不就是数学、英语都大于70的人,这两种情况满足一个就会被筛选
栗子6:查询语文成绩在 [80, 90] 分的同学及语文成绩
这两条语句是等效的
SQL 进行条件查询的时候 , 需要遍历数据带入条件 , 遍历操作在数据集合非常大的时候 , 是比较低效的 . 所以数据库会进行一些内部优化 , 尽可能的避免遍历操作 . 那么这里的 between and 操作其实就是数据库底层的优化 .
栗子7:查询数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
只要数学成绩是()里面任意一个值,都会被筛选出来
下面这样也是可以的
那么我们现在来详细的讲解一下like
运算符。
like
运算符其实就是模糊匹配,相当于描述了一个规则,凡是符合这个规则的字符串都会被筛选出来
我们的like
需要搭配通配符来使用,只需要相关字符串符合你的要求就可以。
%:代表任意个数的任意字符(0个字符也算)
_:代表任意一个字符
举栗子啦~
栗子1:查找姓孙的同学的成绩(%
的使用)
此处这里面的’孙%'就能找到任意以孙开头的字符串,比如
孙红雷
、孙俪
、孙
等等。但是,想要查询
者行孙
就查不到了,我们需要这样来操作
栗子2:_
的使用
模糊匹配在实际开发中也要慎用 , 模糊匹配本身是十分低效的 .
查询语句,和NULL
进行比较
栗子1:查询语文成绩为空的同学
这是咋回事!!?
我们之前说过,
null
的比较如果直接用=
比较的话,此处就相当于null=null
,结果仍然为null
,就被视为false
(假)了,那么针对一些null
的操作,结果仍然是null
,所以我们不能通过这种方式。
针对于空值的比较,我们可以使用<=>
、is null(is not null)
这两种方式
那么is not null
我们也举个栗子:
3.8 分页查询
我们先来看看分页查询到底是咋回事~
我们去任意一个搜索引擎去搜索徐佳莹,我们可以发现,关于徐佳莹的信息有很多,一页装不下
那么我们就可以用到分页查询
但是为什么要分出来很多页,为啥不在一页都显示全?
这是因为网站搜索需要加载很多资源,资源的加载不仅要消耗内存,还会严重占据你的网速,如果我们选择一部分一部分展示,那么展示的效果会更好一点,用户体验感会强一点。
那么在SQL
当中,我们是用limit
来实现分页查询。
语法:从第M
条记录开始,一共返回N
个
select 列名 from 表名 limit N offset M;
-- 另一种写法: select 列名 from 表名 limit M,N;//不推荐
假定我们想要一页就显示三条记录
那么我们如果想显示4、5、6呢?
那么其实打印1、2、3我们还可以这样写。
继续往下打印
limit
同样可以搭配条件,以及order by
等操作来结合使用 , limit
语句一般放在最后
举个栗子:查找总成绩前三的同学
那么我们之前说select
操作对于生产环境的数据库来说,十分危险~
其实危险的程度得看返回的数据是多是少,返回的数据少其实还好,返回的数据比较多就有点糟糕了。
我们可以通过两种手段,让SQL
不至于因为select
操作危险
- 限制更严格的条件(
where
)- 使用
limit
分页打印,实现更稳妥一点的限制