MySQL面试考点整理

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 一、内外连接内连接: 只连接匹配的行左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。

一、内外连接

  • 内连接: 只连接匹配的行
  • 左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
  • 右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
  • 全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。
  • 交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配
drop table users;
drop table address;

create table users(
    id int primary key auto_increment,
    `name` varchar(30)
);

create table address(
    id int primary key auto_increment,
    uid int,
    city varchar(30)
 #   foreign key(uid) references users(id)
);

insert into users (`name`) values("张三");
insert into users (`name`) values("李四");
insert into users (`name`) values("王五");

insert into address (`uid`,`city`) values(1,"上海");
insert into address (`uid`,`city`) values(2,"北京");
insert into address (`uid`,`city`) values(5,"武汉");

select `name`,city from users inner join address on users.id=address.uid;#内连接
select `name`,city from users left join address on users.id=address.uid;#左外连接
select `name`,city from users right join address on users.id=address.uid;#右外连接
select `name`,city from users full join address;#全连接
select `name`,city from users cross join address;#交叉连接,类似于笛卡儿积

1.内连接(inner join)——左右两边都匹配才连接

select `name`,city from users inner join address on users.id=address.uid;
image

2.左外连接(left join)——左边的表全部都保存下来,右边可以为空

select `name`,city from users left join address on users.id=address.uid;
image

3.右外连接(right join)——右边的表全部都保存下来,左边可以为空

select `name`,city from users right join address on users.id=address.uid;
image

4.全连接与交叉连接——两个都是与笛卡儿积类似,都两两相连

image

二、数据库事务的四大特性(ACID)

1.原子性(Atomicity)

原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

2.一致性(Consistency)

如果事务执行之前数据库是一个完整的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整的状态。
数据库的完整状态:当一个数据库中的所有的数据都符合数据库中所定义的所有约束,此时可以称数据库是一个完整的状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

3.隔离型(Isolation)

多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。

4.持久性(Durability)

指一个事务一旦被提交,他对数据库的影响是永久性的。

三、事务级别

1.不同事务级别可能带来的问题

  • 脏读
    脏数据所指的就是未提交的数据。也就是说,一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。

salary=1000

T1 T2
read(salary)——1000
write(salary+2000)——3000
read(salary)——3000
rollback
  • 不可重复读
    一个事务先后读取同一条记录,而事务在两次读取之间该数据被其它事务所修改,则两次读取的数据不同,我们称之为不可重复读。

salary=1000

T1 T2
read(salary)——1000
read(salary)——1000
write(salary+2000)——3000
commit
read(salary)——3000
  • 幻读
    一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。
T1 T2
select * from users where age between 10 and 30;
insert into users(name,age) values("Bob",15);
select * from users where age between 10 and 30;
  • 脏读与不可重复读的区别

    1. 脏读是读取了未提交的数据。一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。
    2. 不可重复读是在两次读取之间有其它事务对数据做了操作。
  • 不可重复读与幻读的区别

    1. 不可重复读的重点是修改,同样的条件, 你读取过的数据, 再次读取出来发现值不一样了。
    2. 幻读的重点在于新增或者删除 (数据条数变化)。同样的条件, 第1次和第2次读出来的记录数不一样。

2.事务的隔离级别

√: 可能出现 ×: 不会出现

脏读 不可重复读 幻读
Read uncommitted(读未提交)
Read committed(读提交) ×
Repeatable read(重复读) × ×
Serializable(序列化) × × ×

四、三大范式

  • 第一范式(1NF):数据表中的每一列(每个字段)必须是不可拆分的最小单元,也就是确保每一列的原子性;
  • 第二范式在第一范式的基础上更进一层,第二范式需要确保数据库表中每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
  • 第三范式需要确保数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。

简而言之:
第1范式:每个表中都有1列,并且该列是不可拆分的最小单元
第2范式:1张表只描述一件事情。如包含用户-订单-商品信息表,应该拆分为3个表。
第3范式:用外键做表的关联。比如:

  • Student表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)
  • 就存在上述关系:学号--> 所在院校 --> (院校地址,院校电话)
  • 这样的表结构,我们应该拆开来:(学号,姓名,年龄,性别,所在院校)--(所在院校,院校地址,院校电话)
    参考链接:https://www.cnblogs.com/1906859953Lucas/p/8299959.html

五、五大约束

1.primary KEY:设置主键约束;
2.UNIQUE:设置唯一性约束,不能有重复值;
3.DEFAULT 默认值约束,height DOUBLE(3,2)DEFAULT 1.2 # height不输入是默认为1,2
4.NOT NULL:设置非空约束,该字段不能为空;
5.FOREIGN key :设置外键约束。

六、常考语法

假设orders表中有如下数据:
{
cust_id: "abc123",
ord_date: ISODate("2012-11-02T17:04:11.102Z"),
status: 'A',
price: 50,
items: [ { sku: "xxx", qty: 25, price: 1 }, { sku: "yyy", qty: 25, price: 1 } ]
}

1.统计orders表中记录数

db.orders.aggregate( [
   {
     $group: {
        _id: null,
        count: { $sum: 1 }
     }
   }
] )

类似mysql:SELECT COUNT(*) AS count FROM orders

2.计算orders表中所有记录的price之和

db.orders.aggregate( [
   {
     $group: {
        _id: null,
        total: { $sum: "$price" }
     }
   }
] )

类似mysql:SELECT SUM(price) AS total FROM orders

3.计算cust_id相同的所有记录的price之和

db.orders.aggregate( [
   {
     $group: {
        _id: "$cust_id",
        total: { $sum: "$price" }
     }
   }
] )

类似mysql:SELECT cust_id,SUM(price) AS total FROM orders GROUP BY cust_id

4.对(cust_id,ord_date)进行分组,并计算每组里面的price之和

db.orders.aggregate( [
   {
     $group: {
        _id: {
           cust_id: "$cust_id",
           ord_date: {
               month: { $month: "$ord_date" },
               day: { $dayOfMonth: "$ord_date" },
               year: { $year: "$ord_date"}
           }
        },
        total: { $sum: "$price" }
     }
   }
] )

类似mysql:SELECT cust_id,ord_date,SUM(price) AS total FROM orders GROUP BY cust_id,ord_date

5.当cust_id相同的记录数大于1时,查询出该cust_id及其对应的记录数

db.orders.aggregate( [
   {
     $group: {
        _id: "$cust_id",
        count: { $sum: 1 }
     }
   },
   { $match: { count: { $gt: 1 } } }
] )

类似mysql:SELECT cust_id,count(*) FROM orders GROUP BY cust_id HAVING count(*) > 1

6.对(cust_id,ord_date)进行分组,并计算每组里面的price之和,返回price之和大于250时的cust_id,ord_date以及price之和

db.orders.aggregate( [
   {
     $group: {
        _id: {
           cust_id: "$cust_id",
           ord_date: {
               month: { $month: "$ord_date" },
               day: { $dayOfMonth: "$ord_date" },
               year: { $year: "$ord_date"}
           }
        },
        total: { $sum: "$price" }
     }
   },
   { $match: { total: { $gt: 250 } } }
] )

类似mysql:SELECT cust_id,ord_date,SUM(price) AS total FROM orders GROUP BY cust_id,ord_date HAVING total > 250

7.计算status='A',且cust_id相同的记录的price之和

db.orders.aggregate( [
   { $match: { status: 'A' } },
   {
     $group: {
        _id: "$cust_id",
        total: { $sum: "$price" }
     }
   }
] )

类似mysql:SELECT cust_id,SUM(price) as total FROM orders WHERE status = 'A' GROUP BY cust_id

8.计算status='A',且cust_id相同的记录的price之和,并且只返回price之和大于250的记录

db.orders.aggregate( [
   { $match: { status: 'A' } },
   {
     $group: {
        _id: "$cust_id",
        total: { $sum: "$price" }
     }
   },
   { $match: { total: { $gt: 250 } } }
] )

类似mysql:SELECT cust_id,SUM(price) as total FROM orders WHERE status = 'A' GROUP BY cust_id HAVING total > 250

9.对于每个唯一的cust_id,将与orders相关联的相应订单项order_lineitem的qty字段进行总计

db.orders.aggregate( [
   { $unwind: "$items" },
   {
     $group: {
        _id: "$cust_id",
        qty: { $sum: "$items.qty" }
     }
   }
] )

类似mysql:SELECT cust_id,SUM(li.qty) as qty FROM orders o,order_lineitem li WHERE li.order_id = o.id GROUP BY cust_id

10.统计(cust_id,ord_date)分组的数量

db.orders.aggregate( [
   {
     $group: {
        _id: {
           cust_id: "$cust_id",
           ord_date: {
               month: { $month: "$ord_date" },
               day: { $dayOfMonth: "$ord_date" },
               year: { $year: "$ord_date"}
           }
        }
     }
   },
   {
     $group: {
        _id: null,
        count: { $sum: 1 }
     }
   }
] )

类似mysql:SELECT COUNT(*) FROM (SELECT cust_id, ord_date FROM orders GROUP BY cust_id, ord_date) as DerivedTable

参考链接:
https://www.cnblogs.com/ilikeballs/p/4341383.html
https://blog.csdn.net/qq_33862644/article/details/79692652
https://www.cnblogs.com/zhoujie/p/mongo1.html

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
22天前
|
SQL 存储 关系型数据库
对线面试官 - 如何理解MySQL的索引覆盖和索引下推
索引下推是MySQL 5.6引入的优化,允许部分WHERE条件在索引中处理,减少回表次数。例如,对于索引(zipcode, lastname, firstname),查询`WHERE zipcode='95054' AND lastname LIKE '%etrunia%'`时,索引下推先过滤zipcode,然后在索引中应用lastname条件,降低回表需求。索引下推可在EXPLAIN的`Using index condition`中看到。
对线面试官 - 如何理解MySQL的索引覆盖和索引下推
|
1月前
|
存储 关系型数据库 MySQL
备战春招系列】历年来关于MySQL高频面试真题的梳理
备战春招系列】历年来关于MySQL高频面试真题的梳理
96 2
|
19天前
|
SQL 关系型数据库 MySQL
MySQL SQL语句面试准备
MySQL SQL语句面试准备
11 0
|
27天前
|
存储 关系型数据库 MySQL
MySQL 面试题及答案整理,最新面试题
MySQL 面试题及答案整理,最新面试题
85 0
|
1月前
|
存储 SQL 关系型数据库
【怒怼大厂面试官】你先说说知道哪些MySQL的高级特性
面试官:上一期博客问了你MySQL主从复制,现在考考你MySQL高级特性吧。分区的一个主要目的是将数据按照一个较粗的粒度分在不同的区域,这样的话就有很多好处。
44 1
|
1月前
|
SQL 网络协议 关系型数据库
【怒怼大厂面试官】听说你精通MySQL?来说说MySQL主从复制
面试官:MySQL主从复制了解吧?嗯嗯了解的。主要是利用了MySQL的Binary Log二进制文件。那我把二进制文件丢给从库,从库复制整个文件吗。噢噢不是的。
47 1
【怒怼大厂面试官】听说你精通MySQL?来说说MySQL主从复制
|
1月前
|
SQL 关系型数据库 MySQL
面试过程中常遇到的Mysql优化方面的面试题
面试过程中常遇到的Mysql优化方面的面试题
45 0
|
8天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
1月前
|
关系型数据库 MySQL 数据库连接
关于MySQL-ODBC的zip包安装方法
关于MySQL-ODBC的zip包安装方法
|
26天前
|
关系型数据库 MySQL 数据库
rds安装数据库客户端工具
安装阿里云RDS的数据库客户端涉及在本地安装对应类型(如MySQL、PostgreSQL)的客户端工具。对于MySQL,可选择MySQL Command-Line Client或图形化工具如Navicat,安装后输入RDS实例的连接参数进行连接。对于PostgreSQL,可以使用`psql`命令行工具或图形化客户端如PgAdmin。首先从阿里云控制台获取连接信息,然后按照官方文档安装客户端,最后配置客户端连接以确保遵循安全指引。
78 1

推荐镜像

更多