前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL表的增删查改

MySQL表的增删查改

作者头像
每天都要进步呀
发布2023-10-16 11:16:46
2400
发布2023-10-16 11:16:46
举报
文章被收录于专栏:C++/LinuxC++/Linux

MySQL基本查询

表的增删改查:CRUD

  • Create(创建)包含insert
  • Retrieve(读取)包含select
  • Update(更新)
  • Delete(删除)

一.增加数据Create

主要是insert。

创建一个学生表:

image-20230726194102971
image-20230726194102971

1.单行数据

单行数据指定列插入:

image-20230726194404757
image-20230726194404757

values左侧为表中属性,右侧为自定义插入的内容,左右两侧安装顺序是一一对应的,如果顺序不同就会导致类型不同而出错。

单行数据全列插入:

image-20230726194739161
image-20230726194739161

将values左侧的属性列全部省略,那么所有属性对应的值都必须插入。

注:into可以省略。

2.多行数据

若想一次插入一批数据,则只需把上面的;替换成,然后继续(数据),最后再分号结束。

多行数据指定列插入:

image-20230726195633647
image-20230726195633647

多行数据全列插入:

image-20230726195423697
image-20230726195423697

3.插入是否更新

由于 主键 或者 唯一键 对应的值已经存在而导致插入失败。

若插入的数据发生主键或者唯一键冲突,就会插入失败,但是我们仍然希望将主键和唯一键之外的的值进行特定的修改,这就用到了 on duplicate key ,即不存在则插入,存在则修改:

image-20230726210059371
image-20230726210059371

其中:

0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等 1 row affected: 表中没有冲突数据,数据被插入 2 row affected: 表中有冲突数据,并且数据已经被更新

此外,通过 MySQL 函数获取受到影响的数据行数

image-20230726210943499
image-20230726210943499

4.替换

还有一种方式能够替代上面的on duplicate key,用replace替换insert同样可以使数据:不存在则插入,存在则修改。

image-20230726211631265
image-20230726211631265

二.查询数据Retrieve

主要是select。(使用频率最高的语句)

表中结构以及插入信息如下。

image-20230727154022109
image-20230727154022109

下面用各种方式进行基本查询。

1.全列查询

全列查询需要 * 通配符完成。

image-20230727154438005
image-20230727154438005

2.指定列查询

指定列查询仍是将表中所有的列拿出来的,只不过我们所筛选的属性并不是全部的数据。

如下语句,都为筛选指定字段的数据:

image-20230727154638284
image-20230727154638284

3.查询字段为表达式

在MySQL数据类型的介绍中,select可以执行相应的各种表达式,函数。而在select的查询中,也可以将这些属性与查询字段拼凑一起。

比如,可以将常数10与特定查询的字段一起显示,这个10也可以换成表达式(1+1):

image-20230727155723715
image-20230727155723715

既然可以查1+1,那么一定也可以查询math+chinese+english:

image-20230727155848239
image-20230727155848239

这样,查询结果中的字段就存在math+chinese+english字段,当然可以用as将这个字段重命名成一个简短的名字total:

image-20230727160041616
image-20230727160041616

甚至as可以省略,这样一来,在查询中,我们可以任意将表字段名在查询结果中重新显示成我们想要的字段名,即表中字段的别名:

image-20230727160304248
image-20230727160304248

查询指定字段中,里面的数据避免不了出现相同的情况,若指向让相同的数据出现一次,则用distinct去重:

image-20230727160559368
image-20230727160559368

需要注意的是null不参与查询。

4.where子句查询

之前的筛选是对表中数据的整体做筛选,即字段筛选,而同一个字段根据数值的不同,通过不同的筛选条件的不同,得到的结果自然也就不同,比如对于分数,想查询60分以上的,那就需要通过where子句的条件来进行筛选。

where筛选影响的是未来查询结果的行数。

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 个)任意字符;_ 表示任意一个字符

image-20230727162538796
image-20230727162538796

通过select + 表达式的方式可以一一验证。

逻辑运算符:

运算符

说明

AND

多个条件必须都为 TRUE(1),结果才是 TRUE(1)

OR

任意一个条件为 TRUE(1), 结果为 TRUE(1)

NOT

条件为 TRUE(1),结果为 FALSE(0)

案例演示:按照条件进行筛选

案例1:英语不及格的同学及英语成绩 ( < 60 )

image-20230727163317911
image-20230727163317911

案例2:语文成绩在 [80, 90] 分的同学及语文成绩

方式一:and连接条件

image-20230727163557843
image-20230727163557843

方式二:BETWEEN a0 AND a1

image-20230727163742981
image-20230727163742981

案例3:数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩

方式一:使用 OR 进行条件连接

image-20230727170458479
image-20230727170458479

方式二:使用 IN 条件

image-20230727170557093
image-20230727170557093

案例4:姓孙的同学 及 孙某同学

类似于这种很模糊的条件,选择like比较运算符进行筛选。

like ‘孙%’:后面任意多个字符。

like ‘孙_’:后面一个字符。

image-20230727172759602
image-20230727172759602

案例5: 语文成绩好于英语成绩的同学

image-20230727172953859
image-20230727172953859

案例6:总分在200分以下的同学

为了方便,这个时候就可以对列进行重命名了,但事实上没有执行成功:

image-20230727173704061
image-20230727173704061

查找语句的执行顺序:

  1. 先执行from找到对应表
  2. 然后where,在表中拿着条件做筛选
  3. 最后select显示

所以,因为在执行where子句时还没有重命名,故也就找不到对应的字段。此外,也不能在筛选条件where中做重命名。故不能缩短语句,只能通过重命名的方式让数据在显示时将字段缩短。

image-20230727174220630
image-20230727174220630

案例7:语文成绩 > 80 并且不姓孙的同学

策略:and与not连用

image-20230727174615844
image-20230727174615844

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

这是一个综合案例

分成两种情况:

  1. 孙某同学(名字任意字数)
  2. 总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80

这两种情况满足其一即可,因此用or连接这两个大条件,通过括号将后面的整体括起来。

image-20230727175301722
image-20230727175301722

案例9:NULL的查询

exam_result表没有空置,所以新建一个表:

image-20230727175839504
image-20230727175839504

查找name=null的人:

image-20230727175946854
image-20230727175946854

查找name不为空的人:

image-20230727180231829
image-20230727180231829

可见,空串不为null。

5.结果排序

查询得到的结果,都是按照一行一行排列的,这时候,就可以根据指定的字段将查询到的结果进行排序。

语法:

  • ASC 为升序(从小到大)默认为ASC
  • DESC 为降序(从大到小)
image-20230727185943057
image-20230727185943057

对此表进行结果排序

1. 同学及数学成绩,按数学成绩升序显示

image-20230727190251620
image-20230727190251620

2. NULL视为比任何值都小,升序出现在最上面

image-20230727190800975
image-20230727190800975

降序也就出现在最下面,不进行演示了。

3. 查询同学各门成绩,依次按 数学降序,英语升序,语文升序的方式显示

image-20230727192222717
image-20230727192222717

其中,asc可以省略,因为默认是升序。

4. 查询同学及总分,由高到低

image-20230727192533869
image-20230727192533869

不过,这里却可以使用别名,即如下方式也可以:

image-20230727192717239
image-20230727192717239

为什么这里又能使用别名了? 排序的原则是先要有合适的数据,在排序。因为这种策略可以最大化提高速度。所以排序的动作是在拿出数据之后的,因此我们select起别名之后就能使用别名了。所以能不能使用别名完全取决于子句的执行顺序。

5. 查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示

根据上面的分析,执行顺序一定是先筛选满足条件的同学,然后再将结果排序。所以思想上自然的就将这两个需求肢解,先筛,再排。

image-20230727193451569
image-20230727193451569

6.筛选分页结果

limit可以限制查询到的数据记录。有三种方式:

方式一:limit n 表示显示前n条数据。

image-20230727195500537
image-20230727195500537

方式二:也可以在一个指定的范围进行筛选:limit m,n表示显示从第m+1条开始显示,显示n条数据。

image-20230727195812761
image-20230727195812761

方式三:limit n offset m;表示从第m条开始,筛选n条结果。m从0算起。

image-20230727204406320
image-20230727204406320

只有数据准备好了,才能显示,limit本质的功能就是“显示”,因此limit执行顺序更靠后(比排序靠后)

对未知表进行查询时,limit能够避免因为表中数据过大,查询全表数据导致数据库卡死

三.更新数据update

一般update会和where子句配合使用,即筛选特定的数据将其进行修改,一旦不用where子句配合筛选,则整个表中的数据都将会被修改。

语法:

案例1:将孙悟空同学的数学成绩变更为 80 分

image-20230728142542095
image-20230728142542095

案例2:将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分

和上一个相比,这个大原则不变,不过这次同时修改两个数据。

image-20230728142840125
image-20230728142840125

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

与前两个不同的是,这个需要order by进行配合。也就是说,分成先查找满足条件的order by,通过limit筛选总成绩倒数前三名,再进行update。

不支持math += 30这种语法。

image-20230728144503754
image-20230728144503754

案例4:将所有同学的语文成绩更新为原来的 2 倍

这个更新的范围就是全表,没有筛选条件

不支持chinese *= 2这种语法。

image-20230728144818880
image-20230728144818880

注意:更新全表的语句慎用

四.删除数据Delete

删除数据是以行为单位的删除,如果删除时不用where子句筛选特定行数据,那么表中的所有数据都会被删除。

语法:

案例1:删除孙悟空同学的考试成绩

image-20230728161419473
image-20230728161419473

案例2:删除总分倒数第一名同学的考试成绩

image-20230728162251195
image-20230728162251195

案例3:删除整张表数据

表内容被删,结构不会被删,结构删用的是drop

方式一:delete from表名

image-20230728162733088
image-20230728162733088

需要注意的是,在这里如果有auto_increment字段,删除数据之后,通过语句:show create table for_delete\G;得到的结果中,其中的auto_increment仍为4,计数器值不会随着表中数据的清除而改变。当插入数据时,会随着此值继续自增。

image-20230728163552738
image-20230728163552738

方式二:截断表

语法:

table可省略。与方式一的区别:

  1. 只能对整表操作,不能像 DELETE 一样针对部分数据操作。
  2. 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚。
  3. 会重置 AUTO_INCREMENT 项
image-20230728164353699
image-20230728164353699

扩展内容

比如bin log, redo log, undo log,这些都是sql溯源之前操作所需要的日志,即为事务。平时的各种sql优化好的语句都会将记录保存在bin log(持久化,保存在文件中),redo log中;undo log是用来做事务回滚的,以及事务的隔离性。数据库一旦出现宕机,redo log可以将数据恢复过来。

持久化方式:

  1. 记录历史SQL语句
  2. 记录数据本身。bin log可以做到主从同步(两个数据库)

所以,truncate不把自己的操作包装成事务,它的操作也不会记录在这些日志里,只是单纯的清空,所以truncate操作一定更快。

五.去重表数据

案例:删除表中的的重复复记录,重复的数据只能有一份

distinct只是在select显示时的去重,不会影响原表中的数据。而现在要的是将表中数据的去重。

去重表数据分三步:

  • 首先,创建另一个表,此表与需要去重的表的结构完全一致。
  • 然后通过select distinct * from 表名,在显示时将重复的去重,再与insert组合,将显示的去重的数据插入到新表中。
  • 最后,将原表重命名进行备份或者直接删掉,新表命名为原表的名字,此新表中的数据就是原表去重后的数据。

实例演示:

原表数据如下:

image-20230728180628878
image-20230728180628878

步骤1.创建新表,命名为no_duplicate_table,结构和duplicate_table相同。

image-20230728180854917
image-20230728180854917

步骤2.select distinct与insert组合,将duplicate_table表中数据筛选去重并插入到no_duplicate_table中。

image-20230728181306496
image-20230728181306496

步骤3.重命名原表与新表,原表备份,新表改名为原表同名

image-20230728181714874
image-20230728181714874

这就完成了去重表数据。

为什么最后是通过rename方式进行的?

通过rename方式,就是单纯的想等一切都就绪了,然后一起放入、更新、生效的。

六.聚合函数

1.聚合函数汇总

函数

说明

COUNT([DISTINCT] expr)

返回查询到的数据的 数量

SUM([DISTINCT] expr)

返回查询到的数据的总和,不是数字没有意义

AVG([DISTINCT] expr)

返回查询到的数据的平均值,不是数字没有意义

MAX([DISTINCT] expr)

返回查询到的数据的最大值,不是数字没有意义

MIN([DISTINCT] expr)

返回查询到的数据的最小值,不是数字没有意义

2.案例演示

image-20230728185441636
image-20230728185441636

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

image-20230728185433465
image-20230728185433465

可以将count函数起别名:

image-20230728185536350
image-20230728185536350

count的括号中,为数字或者'字符'也可以,数字可以任意,甚至可以为小数。

image-20230728185649194
image-20230728185649194

案例2:统计数学成绩有多少个

image-20230728190048709
image-20230728190048709

当然,都是可以起别名的,这就不演示了。

若统计去重后的数据,采用如下:

image-20230728190207253
image-20230728190207253

由于聚合与去重要有先后之分,一旦先聚合再去重,先聚合的结果是5,5就一个数字无法去重,所以这里需要我们需要注意distinct要先执行,即写在括号里。

案例3:统计数学成绩的总分

image-20230728190501645
image-20230728190501645

案例4:统计数学成绩的平均分

image-20230728190548416
image-20230728190548416

案例5:统计英语成绩不及格的人数

image-20230728190732391
image-20230728190732391

案例6:统计英语成绩不及格的同学的英语总分

image-20230728190937197
image-20230728190937197

案例7:统计英语成绩不及格的同学的平均分(两种方式)

image-20230728191152497
image-20230728191152497

案例8:统计英语成绩最高分

image-20230728191504415
image-20230728191504415

需要注意的是,如下这样添加name字段,即name,max(english)是错误的:

image-20230728191657959
image-20230728191657959

因为name没法做聚合,必须先分组再聚合,这就涉及到了group by。暂时若仍想这样做,用where子句筛选最高的成绩就可以了。

案例9:返回 > 70 分以上的数学最低分

image-20230728192003345
image-20230728192003345

七.分组聚合统计group by子句

1.分组查询说明

分组的目的:进行分组之后的聚合统计

分组查询的SQL如下:

说明一下:

  • SQL中大写的表示关键字,[ ]中代表的是可选项。
  • 查询SQL中各语句的执行顺序为:where、group by、select、order by、limit。
  • group by后面的列名,表示按照指定列进行分组查询。

虽然是指定列名进行分组,实际上分组是用该列的不同的行数据来进行分组的。

2.分组查询测试表—雇员信息表

雇员信息表结构内容

雇员信息表中包含三张表,分别是员工表(emp)、部门表(dept)和工资等级表(salgrade)。

员工表(emp)中包含如下字段:

  • 雇员编号(empno)。
  • 雇员姓名(ename)。
  • 雇员职位(job)。
  • 雇员领导编号(mgr)。
  • 雇佣时间(hiredate)。
  • 工资月薪(sal)。
  • 奖金(comm)。
  • 部门编号(deptno)。

部门表(dept)中包含如下字段:

  • 部门编号(deptno)。
  • 部门名称(dname)。
  • 部门所在地点(loc)。

工资等级表(salgrade)中包含如下字段:

  • 等级(grade)。
  • 此等级最低工资(losal)。
  • 此等级最高工资(hisal)。

雇员信息表SQL

雇员信息表的SQL如下:

上述SQL中创建了一个名为scott的数据库,在该数据库中分别创建了部门表(dept)、员工表(emp)和工资等级表(salgrade),并分别向三张表中插入了一些数据用于查询。

将上述SQL保存到文件中,然后在MySQL中使用source命令依次执行文件中的SQL。如下:

image-20230728195119296
image-20230728195119296

执行完文件中的SQL后查看数据库,就能看到多了一个名为scott的数据库。如下:

image-20230728195443994
image-20230728195443994

进入该数据库,在该数据库中就可以看到雇员信息表中的三张表。如下:

image-20230728195522322
image-20230728195522322

其中部门表(dept)的表结构和表中的内容如下:

image-20230728195610867
image-20230728195610867

员工表(emp)的表结构和表中的内容如下:

image-20230728195656660
image-20230728195656660

工资等级表(salgrade)的表结构和表中的内容如下:

image-20230728195757139
image-20230728195757139

显示每个部门的平均工资和最高工资

在group by子句中指明按照部门号进行分组,在select语句中使用avg函数和max函数,分别查询每个部门的平均工资和最高工资。如下:

image-20230728201815130
image-20230728201815130

说明一下: 上述SQL会先将表中的数据按照部门号进行分组,然后各自在组内做聚合查询得到每个组的平均工资和最高工资。

显示每个部门的每种岗位的平均工资和最低工资

与上面不同的是,这个分组会分两次,即先在全表中,按照部门的不同进行分组,分组后的每个小组再根据岗位的不同进行分组。

image-20230728203640674
image-20230728203640674

说明一下:

  • group by子句中可以指明按照多个字段进行分组,各个字段之间使用逗号隔开,分组优先级与书写顺序相同。
  • 比如上述SQL中,当两条记录的部门号相同时,将会继续按照岗位进行分组。

3.HAVING 条件

含有having子句的SQL如下:

说明一下:

  • SQL中大写的表示关键字,[ ]中代表的是可选项。
  • SQL中各语句的执行顺序为:where、group by、select、having、order by、limit。
  • having子句中可以指明一个或多个筛选条件。

having子句和where子句的区别

  • where子句放在表名后面,而having子句必须搭配group by子句使用,放在group by子句的后面。
  • where子句是对整表的数据进行筛选,having子句是对分组后的数据进行筛选。
  • where子句中不能使用聚合函数和别名,而having子句中可以使用聚合函数和别名。

SQL中各语句的执行顺序

  1. 根据where子句筛选出符合条件的记录。
  2. 根据group by子句对数据进行分组。
  3. 将分组后的数据依次执行select语句。
  4. 根据having子句对分组后的数据进行进一步的筛选。
  5. 根据order by子句对数据进行排序。
  6. 根据limit子句筛选若干条记录进行显示。

having案例

案例1:显示平均工资低于2000的部门和它的平均工资

  • 先统计每个部门的平均工资。
  • 然后通过having子句筛选出平均工资低于2000的部门。

统计每个部门的平均工资

在group by子句中指明按照部门号进行分组,在select语句中使用avg函数查询每个部门的平均工资。如下:

image-20230728210407623
image-20230728210407623

显示平均工资低于2000的部门和它的平均工资

在上述SQL的基础上,在having子句中指明筛选条件为平均工资小于2000。如下:

image-20230728210629655
image-20230728210629655

八.CURD总结

CURD无疑是在数据库中操作最多的,都是对表进行各种的增删查改,尤其对于查找,表与表之间因外键的联系等。但无疑,我们在上面的select 等语句,每一个过程都是对表进行操作,即筛选后的数据在逻辑上仍然是一张表,数据库本身也是一种表结构,所以,数据库下一切皆表

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MySQL基本查询
  • 一.增加数据Create
    • 1.单行数据
      • 2.多行数据
        • 3.插入是否更新
          • 4.替换
          • 二.查询数据Retrieve
            • 1.全列查询
              • 2.指定列查询
                • 3.查询字段为表达式
                  • 4.where子句查询
                    • where子句中的各种运算符
                    • 案例演示:按照条件进行筛选
                  • 5.结果排序
                    • 6.筛选分页结果
                    • 三.更新数据update
                    • 四.删除数据Delete
                    • 五.去重表数据
                    • 六.聚合函数
                      • 1.聚合函数汇总
                        • 2.案例演示
                        • 七.分组聚合统计group by子句
                          • 1.分组查询说明
                            • 2.分组查询测试表—雇员信息表
                              • 显示每个部门的平均工资和最高工资
                                • 显示每个部门的每种岗位的平均工资和最低工资
                                  • 3.HAVING 条件
                                  • 八.CURD总结
                                  相关产品与服务
                                  云数据库 MySQL
                                  腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                                  领券
                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档