MySQL初阶 - 易错知识点整理(待更新)

MySQL初阶 - 易错知识点整理(待更新)

Note:这里根据 CSDN Mysql技能树 整理的易错题,可参考MySQL 有这一篇就够MySQL详细学习教程(建议收藏)MySQL 菜鸟教程

一、数据库的使用

Note

  • DDL代表数据定义语言,是一种有助于创建数据库模式SQL命令。DDL中常用的命令有:create,drop,alter,truncaterename等等。
  • DML代表数据操作语言,是一种有助于检索和管理关系数据库中数据的SQL命令。DML中常用的命令有:insert,update,deleteselect等等。

二、数据类型

三、数据修改

四、数据查询

  • select查询,参考sql和MySQL的查询语句的执行顺序
    Note
    • from
    • on
    • join
    • where
    • group by(开始使用select中的别名,后面的语句中都可以使用)
    • avg,sum
    • having
    • select
    • distinct
    • order by
    • limit
      所有的 查询语句都是从from开始执行的,在执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入。
  • where条件查询(指定查询语句的条件限制)
  • 数值计算,参考MySQL运算符(外加优先级)
  • 函数与过程(该题有问题),参考MySQL的存储函数与存储过程的区别存储过程—输入参数(in) / 输出参数(out) / 输入输出参数(inout)MySQL的存储过程—流程控制-case
    Note
    存储函数与存储过程的区别
    • 存储函数有且只有一个返回值,而存储过程可以有多个返回值,也可以没有返回值。
    • 存储函数只能有输入参数,而且不能带in, 而存储过程可以有多个in,out,inout参数
    • 存储过程中的语句功能更强大,存储过程可以实现很复杂的业务逻辑,而函数有很多限制,如不能在函数中使用insert,update,delete,create等语句
    • 存储函数只完成查询的工作,可接受输入参数并返回一个结果,也就是函数实现的功能针对性比较强。
    • 存储过程可以调用存储函数、但函数不能调用存储过程。
    • 存储过程一般是作为一个独立的部分来执行(call调用)。而函数可以作为查询语句的一个部分来调用。
  • 【问】如何使用SQL求交集(joininexists)或差集(not innot exists,参考SQL求交集与差集日期大小比较(DATEDIFF('2017-11-30','2017-11-27')
    Note
    • 假设我有一张会员注册表,表结构和数据如下所示:
      user_id | begin_date | end_date | pay
      100	|  2023-02-11 13:34:38	| 2023-02-12 13:34:43	 | 1
      101	| 2023-02-13 12:30:44	 | 2023-02-17 12:30:47	| 1
      102	| 2023-02-13 12:31:26    | 2023-02-17 12:31:29	| 1
      103	| 2023-02-15 12:35:22 	| 2023-02-16 12:35:28	 | 1
      104	| 2023-02-15 12:35:46	 | 2023-02-16 12:35:55	| 1
      105	| 2023-02-15 12:36:08 	| 2023-02-16 12:36:13	 | 1
      101	| 2023-02-16 12:30:44	 | 2023-02-17 12:30:47	| 1
      102	| 2023-02-16 12:31:26 	| 2023-02-17 12:31:29 	| 1
      101	| 2023-02-18 12:53:49 	| 2023-02-19 12:53:54	 | 1
      105	| 2023-03-12 13:43:39	 |  2023-03-14 13:43:46	| 1
      
      假设我想从上表中筛选出2023.2.14之后新注册的会员个数(标准答案为3,即103,104,105),SQL语句的编写思路如下:
      • 先查询在2023.2.14之前就已经注册的会员,查询字段为DISTINCT(user_id),查询结果记为b
        select DISTINCT(b.user_id) from (
        	select * from vip_test where DATEDIFF(begin_date,'2023-02-14') < 0
        ) as b
        ---
        user_id
        101
        102
        100
        
      • 接着查询在2023.2.14之后注册的会员(这些会员中可能包括2023.2.14之前已注册的会员),查询字段为user_id,查询结果记为a
        select * from vip_test where DATEDIFF(begin_date,'2023-02-14') > 0
        ---
        user_id
        103
        104
        105
        101
        102
        101
        105
        
      • 以查询结果a作为基准,求解不在b.user_id中的a.user_id(即a,b之间的差集,用not innot exists),并且进行去重处理
        #正确答案为3
        select count(DISTINCT(a.user_id)) from (
        		select user_id from vip_test where DATEDIFF(begin_date,'2023-02-14') > 0 ) as a
        where a.user_id not in ( 
        		select DISTINCT(b.user_id) from (
        			select * from vip_test where DATEDIFF(begin_date,'2023-02-14') < 0
        		) as b
        )
        ---
        count(DISTINCT(a.user_id))
        3
        
    • 下面列举出上面例题的两种错误写法
      • 错误写法1:没有使用DATEDIFF进行日期的比较,忽略掉了105
        #错误答案为2
        select DISTINCT(a.user_id) from (
        		select * from vip_test where day(begin_date) > 14 ) as a
        where a.user_id not in ( 
        		select DISTINCT(b.user_id) from (
        			select * from vip_test where day(begin_date) < 14
        		) as b
        )
        ---
        user_id
        103
        104
        
      • 错误写法2:先使用inner join,对左右两表(左表为2023.2.14前,右表为2023.2.14后)中相同的user_id进行内连接,得到两表中user_id的交集,记作a
        select DISTINCT(a.user_id) from (
        	select * from vip_test where DATEDIFF(begin_date,'2023-02-14') < 0 
        ) as a
        INNER JOIN (
        	select * from vip_test where DATEDIFF(begin_date,'2023-02-14') > 0 
        ) as b
        ON a.user_id = b.user_id
        ---
        user_id
        101
        102
        
        接着以全表为基准,使用not in求解不在a.user_id中的用户编号,此时查询结果多了一个100这个用户
      	#错误答案为4
      	select DISTINCT(user_id) from vip_test as c where user_id not in ( 
      		select DISTINCT(a.user_id) from (
      			select * from vip_test where DATEDIFF(begin_date,'2023-02-14') < 0 
      		) as a
      		INNER JOIN (
      			select * from vip_test where DATEDIFF(begin_date,'2023-02-14') > 0 
      		) as b
      		ON a.user_id = b.user_id
      	)
      	---
      	user_id
      	103
      	104
      	105
      	100
      

五、数据库组成

六、查询进阶

七、内置函数

窗口函数

时间日期函数

八、聚合和分组

九、子查询

十、连接查询

参考MySQL中的内连接,左连接,右连接,全连接,交叉连接等相关总结

十一、索引

  • 关于索引的描述,可参考MySQL索引的创建与使用mysql中的聚集索引(聚簇索引)、非聚集索引、稀疏索引、稠密索引
    Note
    • 1)聚集索引索引项的排序方式和表中数据记录排序方式一致的索引。聚簇索引并不是一种单独的索引类型,而是一种数据存储方式
      2)非聚集索引索引顺序物理存储顺序不同
      3)稠密索引:每个索引键值都对应有一个索引项
      4)稀疏索引:相对于稠密索引,稀疏索引只为某些搜索码值建立索引记录(类似于一级间接索引地址
    • InnoDB默认对主键建立聚集索引聚集索引可以应用于非自增的字段;索引可以基于一个或多个字段。
    • 索引的优势
      提高查询效率(降低IO使用率);降低CPU使用率
      比如查询order by age desc因为B+索引树本身就是排好序的,所以再查询如果触发索引,就不用再重新查询了。
    • 索引的弊端
      索引本身很大,可以存放在内存或硬盘上,通常存储在硬盘上;
      索引不是所有情况都使用,比如①少量数据频繁变化的字段 ③很少使用的字段;
      索引会降低增删改的效率。参考mysql索引详解
    • 索引的分类
      1)单值索引
      2)唯一索引
      3)联合索引
      4)主键索引
  • 创建索引(alter table ... add indexcreate index;一个类别category_id包含多种商品,因此对于goods表,不能为goods表创建关于category_id的唯一性索引),可参考MySQL索引的创建与使用别踩坑!使用MySQL唯一索引请注意
    Note
    • 索引创建(表创建之后):
      ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL]  INDEX | KEY  [索引名] (字段名1 [(长度)] [ASC | DESC]) [USING 索引方法];
      
      或者
      CREATE  [UNIQUE | FULLTEXT | SPATIAL]  INDEX  索引名 ON  表名(字段名) [USING 索引方法]
    • 索引说明(索引方法默认使用B+树):
      UNIQUE:可选。表示索引为唯一性索引
      FULLTEXT:可选。表示索引为全文索引
      SPATIAL:可选。表示索引为空间索引
      INDEXKEY:用于指定字段为索引,两者选择其中之一就可以了,作用是 一样的。
      索引名:可选。给创建的索引取一个新名称。
      字段名1:指定索引对应的字段的名称,该字段必须是前面定义好的字段。
      长度:可选。指索引的长度,必须是字符串类型才可以使用。
      ASC:可选。表示升序排列。
      DESC:可选。表示降序排列。
  • 删除索引(alter table ... drop index,可参考MySQL索引的创建与使用
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值