【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);

交叉连接(了解)

​ 格式: 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='唐僧';

外连接查询

​ 左外连接: 以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;

子查询

​ 概念:

​ 一条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次执行完毕后,设置回滚点.

事务的四大特性(ACID)

原子性(Atomicity)

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

一致性(Consistency)

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

隔离性(Isolation)

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

持久性 (Durability)

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

事务的隔离级别

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

问题:

脏读 : 读未提交

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

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

​ 一个事务中两次读取的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这是事务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

作业:

多表和单表练习

你可能感兴趣的:(Mysql数据库,mysql,数据库,sql)