【MySQL】基本查询

表的增删查改

CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除)

1.create创建

  • 语法:

方括号中内容是可以省略的

单行数据+全列插入+指定列插入

一次仅插入一条数据,数据的数量、顺序必须和定义表中的一致,如果每个数据都要插入那么就不用指定要插入数据的列,就叫全列插入,如果插入数据不全就要指定插入列

注意:insert into的into可以省略,但一般加上更直观

多行数据+全列插入+指定列插入

语法和单行数据一样,多行数据插入就是在单行后面用英文逗号隔开,注意values关键字只能出现一次,其余相同

插入否则更新

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

主键冲突:

唯一键冲突:

  • 如果不想冲突时只是单纯的报错提示,而是想将当前数据覆盖更新原数据,那么可以选择进行同步更新语法
    INSERT ... ON DUPLICATE KEY UPDATE
    column = value [, column = value] ...

    绿色线标记初的2 rows affected是什么意思?表中受到影响的数据行数,受影响不仅是数据冲突

    0 行受影响:表数据没任何变化(可能是冲突,也可能是没匹配到数据、更新后值没变化);
    1 行受影响:表中新增 / 删除 / 修改了 1 条数据(可能是无冲突插入,也可能是无冲突更新 / 删除);
    2 行受影响:表中新增 / 删除 / 修改了 2 条数据(可能是无冲突批量操作,也可能是冲突后通过特殊规则允许执行,比如 ON DUPLICATE KEY UPDATE)。
  • 通过ROW_COUNT() 函数获取受到影响的数据行数
    若不受影响返回-1,否则代表实际受到影响的行数

替换

  • replace into语句

主键 或者 唯一键 没有冲突,则直接插入;

主键 或者 唯一键 如果冲突,则删除后再插入,注意新插入位置从当前最大子增值+1的位置处开始,相当于从表尾位置新插入数据,而不是原位置插入

2.retrieve读取

语法:

  • 创建测试表结构,并插入测试数据

全列查询

  • selec * from 表名;
    通常情况下不建议使用进行全列查询,实际业务中数据量特别大,一定要加上筛选条件才能保证效率
    1.查询的列越多,意味着需要传输的数据量越大;
    2.可能会影响到索引的使用。

指定列查询

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

2.1查询字段可以为表达式

  • select语句中允许直接输出常量值,这些常量值会作为 "虚拟列" 在结果集中重复显示,每行的取值都固定为你指定的常量。这种用法常用于生成辅助信息、测试场景(比如临时添加标记列)
  • 表达式包含一个字段
  • 表达式包含多个字段:
  • 为查询结果指定别名:
    语法:
    SELECT column [AS] alias_name [...] FROM table_name;

    as可省略
  • 对结果去重:
    select后加上distinct选项:

2.2where条件

运算符

  • 比较运算符:

NULL 是 "未知",未知与任何事物(包括未知)都无法 "比较",只能 "判断是否为未知"(用 IS NULL)。<=> 解决 "两个值是否逻辑一致(含都未知)"。可以兼容null;IS NULL 解决 "某个值是否是未知"。

mysql中没有==判断是否相等,直接用=

  • 逻辑运算符:

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

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

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

  • 运算符使用测试:
  • 英语不及格的同学及英语成绩 ( < 60 )
    思路:需要同学名字和科目成绩,所以选这两列,再按条件从这两列中筛选,下述测试都是按这种思路来
  • 语文成绩在 [80, 90] 分的同学及语文成绩
    使用and条件连接和between and
  • 数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩

使用or条件或in条件选择

  • 姓孙的同学 及 孙某同学:
    姓孙指名字可以有多个字,孙某规定只能两个字,需要模糊匹配like,分别用%和_。

LIKE 的匹配目标是 "字符串模式",所以必须用单引号界定,否则数据库会把匹配内容当成 "字段名" 或 "关键字",导致语法错误。如果用字段来匹配可以不用单引号

where的别名问题

  • 总分在 200 分以下的同学:

where条件中使用表达式,别名不能在where条件中?

要了解select的执行顺序:

FROM:先确定数据来源(表 / 视图),加载基础数据;

JOIN + ON:多表连接时,执行连接并过滤不符合连接条件的记录;

WHERE:对基础数据做 "行级过滤"(筛选满足条件的行);

GROUP BY:按指定字段分组(若有);

HAVING:过滤分组后的结果(若有,可使用聚合函数);

SELECT:选择要显示的列,此时才会定义别名(如 SELECT score+10 AS add_score);

ORDER BY:对最终结果排序(可使用 SELECT 定义的别名,因执行在 SELECT 之后);

LIMIT:限制返回结果行数(若有)。

所以原因是使用变量名的时机早于定义变量名的时机,那么是否能直接在where条件判断中定义别名,然后直接在select中使用别名?不行:

语法上:SQL 只允许 SELECT 定义列别名,WHERE 不支持别名定义;

逻辑上:WHERE 执行早于 SELECT,其临时计算结果不会保留给 SELECT,即使定义了别名也无法复用。

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

    可以用括号将多个条件判断语句括起来

null的查询与比较

  • null的查询:
    一般使用where 字段名 is not null(is null)
  • null与null的比较

结果排序

  • 语法:

    ascending与descending
    注意:
    1.没有 ORDER BY 子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序
    2.null认为比任何值都小,升序出现在最上面,降序出现在最下面
  • 查询单门成绩,按升降序来排列:
  • 查询同学多门成绩,依次按 数学降序,语文升序,英语升序的方式显示

    ORDER BY 后多个排序字段的核心规则是 "先按第一字段排序,第一字段值相同的记录,再按第二字段排序;第二字段值仍相同的,再按第三字段排序" ,三者是层层依赖的优先级关系

order by子句可用别名

  • 查询总分:
  • order by子句中可以使用别名,为什么?
    因为进行排序前需要先有数据,order by执行顺序在select之后,而where在执行select之前。
    执行在 SELECT 之前的子句(FROM、JOIN、WHERE、GROUP BY、HAVING):看不到别名,不能复用;
    执行在 SELECT 之后的子句(ORDER BY、LIMIT):能看到 SELECT 构造的结果集和别名,可以复用。

筛选分页结果

  • 语法:
    起始下标为 0
    1.从 0 开始,筛选 n 条结果
    SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n;
    2.从 s 开始,筛选 n 条结果
    SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT s, n
    3.从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
    SELECT ... FROM table_name [WHERE ...] [ORDER BY ...] LIMIT n OFFSET s;
    建议:
    对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死
  • 从 0 开始,筛选 n 条结果
  • 按 id 进行分页,每页 3 条记录

    limit n offset s比第二种用法更明确,建议使用

    如果页结果不会有影响,limit的本质功能是显示,数据准备好了才需要显示,所以limit是最后一步执行的。

3.update更新

  • 语法:
    UPDATE table_name SET column = expr [, column = expr ...]

    WHERE ...\] \[ORDER BY ...\] \[LIMIT ...

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

注意上图中set math后需要加限定条件,否则进行了全表更新,尽量不要这么做,也可以一次进行多次更新数据,在set后面用,隔开

  • 将总成绩倒数前三的 3 位同学的语文成绩加上 30 分:

    update可与where条件筛选、order by排序语句、limit分页语句等一起使用,更新成绩后总排名发生了变化。

注意:

数据更新,不支持 math += 30 这种语法,只允许math = math + 30

4.delete删除

  • 语法:
    DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
  • 删除孙悟空同学的考试成绩
  • 删除整张表的信息,测试:
    准备测试表:

当删除整表时,若设置了自增长字段,通过show可以发现即使表数据都被删除了,但创建的字段信息都存在,并且自增长计数器不变,所以delete是dml语句(数据操纵语言)

截断表

  • 语法:
    TRUNCATE [TABLE] table_name
    作用:

1.只能对整表操作,不能像 DELETE 一样针对部分数据操作,比如加上where条件筛选等;清空所有数据,重置表结构,结构更改主要是存储层面的 "重置"(自增主键、表空间、统计信息等),表的逻辑结构(列、索引、约束)完全保留;

2.实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物(后续学习),所以无法回滚

3.会重置 AUTO_INCREMENT 项

4.权限要求更高TRUNCATE 需要 "删除表" 的权限(DROP 权限),而 DELETE 只需要 "删除数据" 的权限(DELETE 权限)------ 因为它本质是对表存储结构的修改,而非单纯的数据删除。

  • 测试:


    现象解释:
    当对表执行 TRUNCATE 后,表数据被清空,同时自增计数器会被重置为初始状态(逻辑上回到未插入数据时的状态)。此时执行 show create table,AUTO_INCREMENT 字段会消失 ------ 因为 MySQL 认为自增计数器尚未被初始化。只有再次插入数据,MySQL 才会重新确定自增的起始值(从 1 开始),并在 show create table 中显示 AUTO_INCREMENT=2(下一次自增的目标值)。

插入查询结果

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


    1.当创建表时想要和另一张表的结构一样时可以使用like,就不用重复再设置字段了,like不会复制数据内容
    2.采用两张表的方式来实现,先创建一个空表,再将原表中去重数据添加进去,最后进行重命名完成。为什么这样?因为能确保操作和数据的稳定性,避免直接对原数据进行修改,如果出现错误可以直接删除新表,重新对原表进行操作,相当于留有备份

5.分组聚合

聚合函数

COUNT([DISTINCT] expr) 返回查询到的数据的 数量

SUM([DISTINCT] expr) 返回查询到的数据的 总和,不是数字没有意义

AVG([DISTINCT] expr) 返回查询到的数据的 平均值,不是数字没有意义

MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义

MIN([DISTINCT] expr) 返回查询到的数据的 最小值,不是数字没有意义

  • 具体测试样例:
  • count的使用:统计总人数

    关于count本质:
    1.COUNT(表达式) 只统计 "表达式结果非 NULL 的行数";
    2.数字是 "永远非 NULL 的常量表达式",每一行都会被计数,最终等价于统计总行数;
    3.不止数字,任何结果非 NULL 的常量表达式(如字符串、确定运算)都能实现同样效果。
  • 关于其他聚合函数的使用都相同,以语句为例

1.统计平均总分:

SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;

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

SELECT MIN(math) FROM exam_result WHERE math > 70;

3.返回英语最高分:

SELECT MAX(english) FROM exam_result;

4.统计数学成绩总分

SELECT SUM(math) FROM exam_result;

group by子句的使用

  • 在select中使用group by 子句可以对指定列进行分组查询:
    select column1, column2, ... from table group by column;
  • 测试,准备一个雇员信息表
  • 分组就是把一组按照一定条件拆成了多个组,进行各自组内的统计,也就是将一张表拆成子表,所以只要能完成对一张表的操作,就能完成多表的聚合操作
  • 如何显示每个部门的平均工资和最高工资

    通过group by指定列名,实际是用该列的不同行数据来进行分组的
  • 显示每个部门的每种岗位的平均工资和最低工资
  • 显示平均工资低于2000的部门和它的平均工资

    这里的having是对聚合后的统计数据,做条件筛选,作用类似where
  • having和where的区别?
    主要体现在条件的筛选阶段
  • having和where能否相互替代?
    不行,二者是 "先后配合" 关系:先 WHERE 筛行,再 GROUP BY 分组聚合,最后 HAVING 筛组,缺一不可,无法替代。
    简单记:WHERE 管行,HAVING 管组;聚合之前用 WHERE,聚合之后用HAVING
    存在特殊情况:
    无 GROUP BY 时,HAVING 会退化为 WHERE(MySQL 特有行为):

注意:

聚合时要求选择出来的所有字段都能进行聚合,name不能聚合。

只有在order by后面出现的字段才能在select中进行聚合,否则会报错

  • 对查询结果的理解:
    不仅仅是磁盘上表结构导入到mysql,真实存在的表才叫做表,通过语句中间筛选出来的包括最终结果,全部都是逻辑上的表,mysql一切皆表。
    "一切皆表" 的核心体现:数据的 "输入"(物理表、系统表、临时表)和 "输出"(查询结果集),都统一为 "表" 的结构,SQL 语法可以无缝复用。

不是真的所有都是表,而是抽象为表

一切皆表是抽象层面的设计,不是说 MySQL 内部所有组件都是表:

比如日志文件(binlog、redo log)、索引结构(B + 树)、存储引擎的底层数据页,这些不是表;

但对用户 / 开发者来说,所有需要访问数据的操作,都通过 "表" 这个统一接口实现------ 不用关心底层存储,只用掌握 SQL 表操作,就能处理所有数据场景。

所以我们只要能处理好单表的CURD,所有的sql场景,我们全部能用统一的方式进行

相关推荐
last_zhiyin25 分钟前
Oracle sql tuning guide 翻译 Part 6-5 --- Hint使用报告的操作方法和例子
数据库·sql·oracle·sql tunning
Rysxt_29 分钟前
Spring Boot SPI 教程
java·数据库·sql
q***471838 分钟前
使用Canal将MySQL数据同步到ES(Linux)
linux·mysql·elasticsearch
避避风港1 小时前
MySQL 从入门到实战
数据库·mysql
s***4531 小时前
MSSQL2022的一个错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.16.0”提供程序
数据库·microsoft
能鈺CMS2 小时前
能鈺CMS · 虚拟发货源码
java·大数据·数据库
泡沫·2 小时前
4.iSCSI 服务器
运维·服务器·数据库
胡八一2 小时前
解决PHP未检测到您服务器环境的sqlite3数据库扩展报错
服务器·数据库·php
Wang's Blog3 小时前
MongoDB小课堂: 游标操作与文档投影技术深度解析
数据库·mongodb