• 【Mysql】第4篇--多表查询和事务


    三范式

    ​ 范式: 设计数据库表的规则

    ​ 第一范式:

    ​ 每一列不能再拆分,查询出的结果不需要进一步处理,可以直接使用

    ​ 第二范式:

    ​ 每张数据库表必须要有主键

    ​ 可以解决数据冗余(重复)问题 (一张表只能描述一件事情)

    ​ 第三范式

    ​ 从表的外键必须使用主表的主键

    多表查询 ★★★

    单表查询: select * from 表名;

    多表查询: select * from 表1,表2,表3… ;

    建表语句:
    -- 创建部门表
    CREATE TABLE dept (
    	id INT PRIMARY KEY AUTO_INCREMENT,
    	NAME VARCHAR(20)
    );
    INSERT INTO dept (NAME) VALUES ('开发部'),('市场部'),('财务部'),('销售部');
    -- 创建员工表
    CREATE TABLE emp (
    	id INT PRIMARY KEY AUTO_INCREMENT,
    	`name` VARCHAR(10), -- 员工姓名
    	gender CHAR(1), -- 性别
    	salary DOUBLE, -- 工资
    	join_date DATE, -- 入职日期
    	dept_id INT, -- 所属部门id (外键字段)
    	FOREIGN KEY (dept_id) REFERENCES dept(id) -- 外键约束
    );
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('孙悟空','男',7200,'2013-02-24',1);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('猪八戒','男',3600,'2010-12-02',2);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('唐僧','男',9000,'2008-08-08',2);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('白骨精','女',5000,'2015-10-07',3);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('蜘蛛精','女',4500,'2011-03-14',1);
    INSERT INTO emp(NAME,gender,salary,join_date,dept_id) VALUES('沙僧','男',6666,'2013-02-24',NULL);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    交叉连接(了解)

    ​ 格式: select * from 表1,表2…;
    ​ 产生笛卡尔积

    内连接查询

    ​ 隐式内连接: ★★★

    ​ select * from 表1,表2 where 条件;

    ​ 显示内连接

    ​ select * from 表1 [inner] join 表2 on 关联条件 where 筛选条件;

    ​ on: 后跟的两个表的关联条件

    ​ where: 后跟的是对结果的筛选条件

    - 1.查询唐僧的信息,显示员工id,姓名,性别,工资和所在的部门名称
    -- 内连接查询-隐式内连接
    # a.确定要查询的表 emp dept
    SELECT * FROM emp,dept;
    # b.找两张表的关联条件 emp.dept_id = dept.id
    SELECT * FROM emp,dept WHERE emp.dept_id = dept.id;
    # c.确定要查询的结果数据
    SELECT e.id,e.name,e.gender,e.salary,d.name AS "部门名称"
    	FROM emp AS e,dept AS d
    	WHERE e.dept_id = d.id AND e.name='唐僧';
    -- 内连接查询-显式内连接
    # a.确定要查询的表 emp dept
    SELECT * FROM emp INNER JOIN dept;
    # b.找两张表的关联条件 emp.dept_id = dept.id
    SELECT * 
    	FROM emp INNER JOIN dept
    	ON emp.dept_id = dept.id;
    # c.确定要查询的结果数据
    SELECT e.id,e.name,e.gender,e.salary,d.name AS "部门名称"
    	FROM emp AS e INNER JOIN dept d
    	ON e.dept_id = d.id
    	WHERE e.name='唐僧';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    外连接查询

    ​ 左外连接: 以join左边的表为主,查询其所有数据信息,根据条件查询join右边的表,将满足条件的数据查询出来,如果没有满足条件的数据,则填充null

    ​ select * from 表1 left [outer] join 表2 on 关联条件 where 筛选条件;

    ​ 右外连接: 以join右边的表为主,查询其所有数据信息,根据条件查询join左边的表,将满足条件的数据查询出来,如果没有满足条件的数据,则填充null

    ​ select * from 表1 rigth [outer] join 表2 on 关联条件 where 筛选条件;

    -- 2.查询所有员工及所属部门
    SELECT * 
    	FROM emp LEFT OUTER JOIN dept 
    	ON emp.dept_id=dept.id;
    	
    SELECT * FROM dept RIGHT OUTER JOIN emp
    	ON emp.dept_id=dept.id;
    -- 3.查询所有部门及所含员工
    SELECT * FROM dept LEFT JOIN emp 
    	ON emp.dept_id=dept.id;
    
    SELECT * FROM emp RIGHT JOIN dept
    	ON emp.dept_id=dept.id;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    子查询

    ​ 概念:

    ​ 一条sql执行的结果是另一条sql的条件

    ​ 子查询结果:

    ​ 单一结果(单行单列): select * from 表名 where (= 子查询结果)

    ​ 单列多值(多行单列): select * from 表名 where (in 子查询结果)

    ​ 多列多值(多行多列): select * from (子查询结果) as 别名 where …

    事务

    事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败

    转账案例:

    ​ tom 给 rose转账(100元)

    ​ account: 账户表

    ​ name money

    ​ tom 1000

    ​ rose 1000

    ​ 从tom帐号上减100元

    ​ update account set money = money - 100 where name = ‘tom’;

    ​ 给rose帐号上加100元

    ​ update account set money = money + 100 where name = ‘rose’;

    完成事务操作

    查看mysql的事务控制方式

    ​ mysql的事务控制是自动的,默认一条sql就是一个事务:

    ​ mysql的事务控制是自动的: sql语句执行完毕后,mysql会自动将事务提交.

    ​ 每条sql语句执行完毕后,立即将执行结果写入到数据库中

    ​ 查看mysql的事务提交状态:

    ​ show variables like ‘%commit%’;

    ​ 开启手动事务(关闭自动事务提交)

    ​ set autocommit = 0;

    ​ 关闭mysql手动事务(开启自动事务提交)

    ​ set autocommit = 1;

    SQL语句

    ​ start transaction; | begin; 开启手动事务控制

    ​ commit; 提交事务(将事务中的sql语句执行结果保存到数据库中)

    ​ rollback; 回滚事务(回到事务开启前的状态)

    ​ 了解: 设置事务的回滚点

    ​ savepoint 名称;

    ​ 1000操作 1 2 3…100(“设置回滚点”)…200(“设置回滚点”)…900(“设置回滚点”)…999(失败)

    ​ rollback to 名称; 回到指定的回滚点上

    让tom给rose转账:
    	每次转100,5次
    	在第2次执行完毕后,设置回滚点.
    	在第4次执行完毕后,设置回滚点.
    
    • 1
    • 2
    • 3
    • 4

    事务的四大特性(ACID)

    原子性(Atomicity)

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

    一致性(Consistency)

    ​ 事务前后数据的完整性必须保持一致

    隔离性(Isolation)

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

    持久性 (Durability)

    ​ 指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

    事务的隔离级别

    1.将隔离级别调到最低
    show variables like "%isolation%"; -- 查询mysql的隔离级别
    set global transaction isolation level read uncommitted; -- 设置成功后,需要重启mysql
    
    
    • 1
    • 2
    • 3
    • 4

    问题:

    脏读 : 读未提交

    ​ 一个事务读取到了另一个事务中尚未提交的数据

    不可重复读 (针对修改的)

    ​ 一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这是事务update时引发的问题

    幻读|虚读

    ​ 一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致的,这是insert或delete时引发的问题

    解决问题

    设置事务的隔离级别

    ​ set global transaction isolation level 级别字符串;

    1.读未提交 (最低级别,以上情况均无法保证。)

    ​ read uncommitted:

    ​ 脏读: 读未提交

    ​ 不可重复读: 多次读取到的数据不一致.(update)

    ​ 幻读: 一个事务读取到了另外一个事务添加后删除的数据

    2.读已提交 (可避免脏读情况发生。)

    ​ read committed

    ​ 只能解决脏读问题

    3.可重复读 (可避免脏读、不可重复读情况的发生。 mysql的默认隔离级别)

    ​ repeatable read

    4.串行化 (可避免脏读、不可重复读、幻读(虚读)情况的发生)

    ​ 使用serializable隔离级别,一个事务没有执行完,其他事务的SQL执行不了,可以挡住幻读

    ​ serializable

    查询mysql的隔离级别:
    	show variables like "%isolation%";  // REPEATABLE-READ
    
    • 1
    • 2

    作业:

    多表和单表练习

  • 相关阅读:
    课程目录《C语言程序设计:一个小球的编程之旅》
    睿趣科技:抖音小店新手运营攻略
    SpringBoot入门案例
    Hadoop3 - MapReduce ORC 列式存储
    全国双非院校考研信息汇总整理 Part.3
    深度学习——池化层笔记+代码
    利用HbuilderX制作简单网页: HTML5期末大作业——html5漫画风格个人主页
    02_stack栈
    使用 Redis 如何统计一亿个 keys ?
    禁止EditView自动弹出系统软键盘_Android基础篇(Java)
  • 原文地址:https://blog.csdn.net/qq_41250372/article/details/125462378