MySQL 学习笔记(基础篇 Day3)

「写在前面」

本文为黑马程序员 MySQL 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容:
1. MySQL 学习笔记(基础篇 Day1)
2. MySQL 学习笔记(基础篇 Day2)


目录

  • 5 多表查询
    • 5.1 多表关系
    • 5.2 多表查询概述
    • 5.3 内连接
    • 5.4 外连接
    • 5.5 自连接
    • 5.6 子查询
    • 5.7 多表查询案例
  • 6 事务
    • 6.1 事务简介
    • 6.2 事务操作
    • 6.3 事务四大特性
    • 6.4 并发事务问题
    • 6.5 事务隔离级别

5 多表查询

5.1 多表关系

P37:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=37

项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:

  • 一对多(多对一)
  • 多对多
  • 一对一
5.1.1 一对多
  • 案例: 部门 与 员工的关系
  • 关系: 一个部门对应多个员工,一个员工对应一个部门
  • 实现: 在多的一方建立外键,指向一的一方的主键
alt
5.1.2 多对多
  • 案例: 学生 与 课程的关系
  • 关系: 一个学生可以选修多门课程,一门课程也可以供多个学生选择
  • 实现: 建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
alt

对应的SQL脚本:

# 创建 student 表
create table student(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '姓名',
no varchar(10) comment '学号'
) comment '学生表';
# 向 student 表中插入数据
insert into student values (null, '黛绮丝', '2000100101'),(null, '谢逊', '2000100102'),(null, '殷天正', '2000100103'),(null, '韦一笑', '2000100104');

# 创建 course 表
create table course(
id int auto_increment primary key comment '主键ID',
name varchar(10) comment '课程名称'
) comment '课程表';
# 向 course 表中插入数据
insert into course values (null, 'Java'), (null, 'PHP'), (null , 'MySQL') ,(null, 'Hadoop');

# 创建 student_course 中间表
create table student_course(
id int auto_increment comment '主键' primary key,
studentid int not null comment '学生ID',
courseid int not null comment '课程ID',
constraint fk_courseid foreign key (courseid) references course (id),
constraint fk_studentid foreign key (studentid) references student (id)
) comment '学生课程中间表';
# 插入数据关联两方主键
insert into student_course values (null,1,1),(null,1,2),(null,1,3),(null,2,2),(null,2,3),(null,3,4);
5.1.3 一对一
  • 案例: 用户 与 用户详情的关系
  • 关系: 一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
  • 实现: 在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)
alt

5.2 多表查询概述

P38:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=38

多表查询就是指从多张表中查询数据。

原来查询单表数据,执行的SQL形式为:

select * from emp;

而在多表查询中,我们是需要消除无效的笛卡尔积的,只保留两张表关联部分的数据:

select * from emp , dept where emp.dept_id = dept.id;

多表查询分类:

  • 连接查询
    • 内连接:相当于查询A、B交集部分数据
    • 外连接:
      • 左外连接:查询左表所有数据,以及两张表交集部分数据
      • 右外连接:查询右表所有数据,以及两张表交集部分数据
    • 自连接:当前表与自身的连接查询,自连接必须使用表别名
  • 子查询
alt

5.3 内连接

P39:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=39

内连接查询的是两张表交集部分的数据

1. 隐式内连接

SELECT 字段列表 FROM1 , 表2 WHERE 条件 ... ;

2. 显式内连接

SELECT 字段列表 FROM1 [ INNER ] JOIN2 ON 连接条件 ... ;

案例:

# A. 查询每一个员工的姓名 , 及关联的部门的名称 (隐式内连接实现)
select emp.name , dept.name from emp , dept where emp.dept_id = dept.id ;

# B. 查询每一个员工的姓名 , 及关联的部门的名称 (显式内连接实现)
select e.name, d.name from emp e inner join dept d on e.dept_id = d.id;

5.4 外连接

P40:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=40

1. 左外连接

左外连接相当于查询表1(左表)的所有数据,当然也包含表1和表2交集部分的数据。

SELECT 字段列表 FROM1 LEFT [ OUTER ] JOIN2 ON 条件 ... ;

2. 右外连接

右外连接相当于查询表2(右表)的所有数据,当然也包含表1和表2交集部分的数据。

SELECT 字段列表 FROM1 RIGHT [ OUTER ] JOIN2 ON 条件 ... ;

案例:

# A. 查询emp表的所有数据, 和对应的部门信息
select e.*, d.name from emp e left outer join dept d on e.dept_id = d.id;

# B. 查询dept表的所有数据, 和对应的员工信息(右外连接)
select d.*, e.* from emp e right outer join dept d on e.dept_id = d.id;

5.5 自连接

5.5.1 自连接查询

P41:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=41

自连接查询,顾名思义,就是自己连接自己,也就是把一张表连接查询多次。

自连接的查询语法:

SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件 ... ;

案例:

# A. 查询员工 及其 所属领导的名字
select a.name , b.name from emp a , emp b where a.managerid = b.id;

# B. 查询所有员工 emp 及其领导的名字 emp , 如果员工没有领导, 也需要查询出来
select a.name '员工', b.name '领导' from emp a left join emp b on a.managerid = b.id;

注意事项:在自连接查询中,必须要为表起别名,要不然我们不清楚所指定的条件、返回的字段,到底是哪一张表的字段。

5.5.2 联合查询

P42:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=42

对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。

语法:

SELECT 字段列表 FROM 表A ...
UNION [ ALL ]
SELECT 字段列表 FROM 表B ....;
  • 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
  • union all 会将全部的数据直接合并在一起,union 会对合并之后的数据去重。

案例:

# A. 将薪资低于 5000 的员工 , 和 年龄大于 50 岁的员工全部查询出来
select * from emp where salary < 5000
union
select * from emp where age > 50;

union 联合查询,会对查询出来的结果进行去重处理。

注意:如果多条查询语句查询出来的结果,字段数量不一致,在进行union/union all联合查询时,将会报错。

5.6 子查询

5.6.1 概述

P43:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=43

1. 概念

SQL语句中嵌套SELECT语句,称为嵌套查询,又称子查询。

SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 );

子查询外部的语句可以是INSERT / UPDATE / DELETE / SELECT 的任何一个

2. 分类

根据子查询结果不同,分为:
A. 标量子查询(子查询结果为单个值)
B. 列子查询(子查询结果为一列)
C. 行子查询(子查询结果为一行)
D. 表子查询(子查询结果为多行多列)

根据子查询位置,分为:
A. WHERE之后
B. FROM之后
C. SELECT之后

5.6.2 标量子查询

P44:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=44

子查询返回的结果是单个值(数字、字符串、日期等),最简单的形式,这种子查询称为标量子查询。

常用的操作符:= <> > >= < <=

案例:

# A. 查询 "销售部" 的所有员工信息
select * from emp where dept_id = (select id from dept where name = '销售部');

# B. 查询在 "方东白" 入职之后的员工信息
select * from emp where entrydate > (select entrydate from emp where name = '方东白');
5.6.3 列子查询

P45:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=45

子查询返回的结果是一列(可以是多行),这种子查询称为列子查询。

常用的操作符:IN 、NOT IN 、 ANY 、SOME 、 ALL

操作符描述
IN在指定的集合范围之内,多选一
NOTIN 不在指定的集合范围之内
ANY子查询返回列表中,有任意一个满足即可
SOME与ANY等同,使用SOME的地方都可以使用ANY
ALL子查询返回列表的所有值都必须满足

案例:

# A. 查询 "销售部" 和 "市场部" 的所有员工信息
select * from emp where dept_id in (select id from dept where name = '销售部' or name = '市场部');

# B. 查询比 财务部 所有人工资都高的员工信息
select * from emp where salary > all ( select salary from emp where dept_id = (select id from dept where name = '财务部') );

# C. 查询比研发部其中任意一人工资高的员工信息
select * from emp where salary > any ( select salary from emp where dept_id = (select id from dept where name = '研发部') );
5.6.4 行子查询

P46:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=46

子查询返回的结果是一行(可以是多列),这种子查询称为行子查询。

常用的操作符:= 、<> 、IN 、NOT IN

案例:

# A. 查询与 "张无忌" 的薪资及直属领导相同的员工信息 ;
select * from emp where (salary,managerid) = (select salary, managerid from emp where name = '张无忌');
5.6.5 表子查询

P47:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=47

子查询返回的结果是多行多列,这种子查询称为表子查询。

常用的操作符:IN

案例:

# A. 查询与 "鹿杖客" , "宋远桥" 的职位和薪资相同的员工信息
select * from emp where (job,salary) in ( select job, salary from emp where name = '鹿杖客' or name = '宋远桥' );

# B. 查询入职日期是 "2006-01-01" 之后的员工信息 , 及其部门信息
select e.*, d.* from (select * from emp where entrydate > '2006-01-01') e left join dept d on e.dept_id = d.id ;

5.7 多表查询案例

P48:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=48

P49:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=49

P50:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=50

6 事务

6.1 事务简介

P51:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=51

事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败

就比如: 张三给李四转账 1000 块钱,张三银行账户的钱减少 1000,而李四银行账户的钱要增加 1000。这一组操作就必须在一个事务的范围内,要么都成功,要么都失败。

注意: 默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐式的提交事务。

6.2 事务操作

P52:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=52

数据准备:

drop table if exists account;

create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '余额'
) comment '账户表';

insert into account(name, money) VALUES ('张三',2000), ('李四',2000);
6.2.1 未控制事务

1. 测试正常情况

-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';

测试完毕之后检查数据的状态, 可以看到数据操作前后是一致的

alt

2. 测试异常情况

-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
出错了....
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';

我们把数据都恢复到2000, 然后再次一次性执行上述的SQL语句(出错了.... 这句话不符合SQL语法,执行就会报错),检查最终的数据情况, 发现数据在操作前后不一致了

alt
6.2.2 控制事务一

1. 查看/设置事务提交方式

SELECT @@autocommit ;
SET @@autocommit = 0 ;

2. 提交事务

COMMIT;

3. 回滚事务

ROLLBACK;

注意:上述的这种方式,我们是修改了事务的自动提交行为, 把默认的自动提交修改为了手动提交, 此时我们执行的DML语句都不会提交, 需要手动的执行commit进行提交。

6.2.3 控制事务二

1. 开启事务

START TRANSACTIONBEGIN ;

2. 提交事务

COMMIT;

3. 回滚事务

ROLLBACK;

转账案例:

-- 开启事务
start transaction
-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
-- 如果正常执行完毕, 则提交事务
commit;
-- 如果执行过程中报错, 则回滚事务
-- rollback;

6.3 事务四大特性

P53:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=53

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

上述就是事务的四大特性,简称ACID。

alt

6.4 并发事务问题

P54:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=54

1. 赃读

一个事务读到另外一个事务还没有提交的数据。

alt

比如B读取到了A未提交的数据

2. 不可重复读

一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读

alt

事务A两次读取同一条记录,但是读取到的数据却是不一样的

3. 幻读

一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了 "幻影"

alt

6.5 事务隔离级别

P55:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=55

为了解决并发事务所引发的问题,在数据库中引入了事务隔离级别。主要有以下几种:

隔离级别脏读不可重复读幻读
Read uncommitted
Read committed×
Repeatable Read(默认)××
Serializable×××

1. 查看事务隔离级别

SELECT @@TRANSACTION_ISOLATION;

2. 设置事务隔离级别

SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

注意:事务隔离级别越高,数据越安全,但是性能越低。

事物小结

P56:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=56

基础篇总结

P57:https://www.bilibili.com/video/BV1Kr4y1i7ru?p=57


「结束」

注:本文为个人学习笔记,仅供大家参考学习,不得用于任何商业目的。如有侵权,请联系作者删除。

alt

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/528951.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch 的开源分析可视化工具--Kibana 安装 使用

1、简介 Kibana 是一款 Elasticsearch 的开源分析可视化工具&#xff0c;能够与存储在 Elasticsearch 中的数据进行交互&#xff0c;在开发中能够监控Elasticsearch中的数据&#xff0c;并且能够执行命令操作Elasticsearch中的数据。 2、Kibana 的下载与安装 2.1、Kibana 下载…

NIN网络中的网络

是什么 intro LeNet→AlexNet→VGG→NiN→GoogLeNet→ResNetLeNet→AlexNet→VGG 卷积层模块充分抽取空间特征全连接层输出分类结果AlexNet & VGG 改进在于把两个模块加宽 、加深&#xff08;加宽指增加通道数&#xff0c;那加深呢&#xff1f;&#xff08;层数增加叭 Ni…

【linux】02 :Linux基础命令

1.掌握linux系统的目录结构 linux只有一个顶级目录&#xff0c;称之为&#xff1a;根目录。 windows系统有多个顶级目录&#xff0c;即各个盘符。 2.linux路径的描述方式 /在Linux中的表示&#xff1a;出现在开头表示根目录&#xff0c;出现在后面表示层级关系。 3.什么是命…

【linux进程信号】信号的产生

【Linux进程信号】信号的产生 目录 【Linux进程信号】信号的产生信号概念生活中的信号技术应用角度的信号注意信号概念用kill -l命令可以察看系统定义的信号列表信号处理常见方式概览 产生信号通过终端按键产生信号调用系统函数向进程发信号由软件条件产生信号由硬件异常产生信…

DEYO: DETR with YOLO for End-to-End Object Detection论文翻译

DEYO&#xff1a;DETR与YOLO用于端到端目标检测 摘要 DETR的训练范式在很大程度上取决于在ImageNet数据集上预训练其骨干。然而&#xff0c;由图像分类任务和一对一匹配策略提供的有限监督信号导致DETR的预训练不充分的颈部。此外&#xff0c;在训练的早期阶段匹配的不稳定性会…

python螺旋数字矩阵

python螺旋数字矩阵 给出数字个数n (0<n ≤999)和行数m (0<m ≤ 999)。从左上角的1开始&#xff0c;按照顺时针螺旋向内写方式&#xff0c;输出1-n&#xff0c;依次写出2,3.….&#xff0c;最终形成一个m行的矩阵。 1.每行数字的个数一样多 2.列的数量尽可能少 3.填充数字…

大数据 - Spark系列《十二》- 名词术语理解

Spark系列文章&#xff1a; 大数据 - Spark系列《一》- 从Hadoop到Spark&#xff1a;大数据计算引擎的演进-CSDN博客 大数据 - Spark系列《二》- 关于Spark在Idea中的一些常用配置-CSDN博客 大数据 - Spark系列《三》- 加载各种数据源创建RDD-CSDN博客 大数据 - Spark系列《…

Elasticsearch 通过索引阻塞实现数据保护深入解析

Elasticsearch 是一种强大的搜索和分析引擎&#xff0c;被广泛用于各种应用中&#xff0c;以其强大的全文搜索能力而著称。 不过&#xff0c;在日常管理 Elasticsearch 时&#xff0c;我们经常需要对索引进行保护&#xff0c;以防止数据被意外修改或删除&#xff0c;特别是在进…

python coding with ChatGPT 打卡第22天| 二叉搜索树的操作:插入、删除、修剪、转换

相关推荐 python coding with ChatGPT 打卡第12天| 二叉树&#xff1a;理论基础 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历 python coding with ChatGPT 打卡第15天| 二叉树&#xff1a;翻转…

day60 安装MySql数据库

1如何安装MySQL数据库 2数据库概念 3数据库语言 1 SQL&#xff08;数据结构化查询语句&#xff09; 2分类 1数据库查询语言DQL select 2数据库操作语言DML insert&#xff0c;update&#xff0c;delete 3数据库定义语言DDL create&#xff0c;alter修改&am…

JAVA实战开源项目:超市自助付款系统(Vue+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 商品类型模块2.2 商品模块2.3 超市账单模块 三、界面展示3.1 登录注册模块3.2 超市商品类型模块3.3 超市商品模块3.4 商品购买模块3.5 超市账单模块 四、部分源码展示4.1 实体类定义4.2 控制器接口 五、配套文档展示六、…

傅里叶变换pytorch使用

参考视频&#xff1a;1 傅里叶变换原理_哔哩哔哩_bilibili 傅里叶变换是干嘛的&#xff1a; 傅里叶得到低频、高频信息&#xff0c;针对低频、高频处理能够实现不同的目的。 傅里叶过程是可逆的&#xff0c;图像经过傅里叶变换、逆傅里叶变换后&#xff0c;能够恢复到原始图像…