java学习记录三十:MySql基础三:子查询、事务

一、子查询

一、解释

子查询嵌套查询, 查询的语句可以作为另外一个查询语句的条件, 直观一点: 一条语句里面包含了多个select,里面嵌套的那个查询就是子查询

  • 一个查询语句的结果作为另一个查询语句的条件
  • 有查询的嵌套,内部的查询称为子查询
  • 子查询要使用括号
  • 子查询结果的三种情况:
    1. 子查询的结果是一个值的时候
    2. 子查询结果是单列多行的时候
    3. 子查询的结果是多行多列

二、三种结果的查询

1.子查询的结果是一个值的时候

子查询结果只要是单个值,肯定在WHERE后面作为条件
SELECT 查询字段 FROM 表 WHERE 字段[= > < <>](子查询);

例子:查询工资大于5000的员工,来自于哪些部门的名字
1.查询最高工资是多少

SELECT MAX(salary) FROM emp;

2.根据最高工资到员工表查询到对应的员工信息

SELECT * FROM emp WHERE salary=(SELECT MAX(salary) FROM emp);

例子:查询开发部与财务部所有的员工信息
1.查询平均工资是多少

SELECT AVG(salary) FROM emp

2.到员工表查询小于平均的员工信息

 SELECT * FROM emp WHERE salary < (SELECT AVG(salary) FROM emp);

2.子查询结果是单列多行的时候

子查询结果只要是单列,肯定在WHERE后面作为条件
子查询结果是单列多行,结果集类似于一个数组,父查询使用IN运算符

SELECT 查询字段 FROMWHERE 字段 IN (子查询);

例子:查询工资大于5000的员工,来自于哪些部门的名字**
1.先查询大于5000的员工所在的部门id

SELECT dept_id FROM emp WHERE salary > 5000;

2.再查询在这些部门id中部门的名字

SELECT dept.name FROM dept WHERE dept.id IN (SELECT dept_id FROM emp WHERE salary > 5000);

例子二:查询开发部与财务部所有的员工信息
1.先查询开发部与财务部的id

SELECT id FROM dept WHERE NAME IN('开发部','财务部');

2.再查询在这些部门id中有哪些员工

SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME IN('开发部','财务部'));

3.子查询的结果是多行多列

子查询结果只要是多行多列,肯定在FROM后面作为
SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;
子查询作为表需要取别名,否则这张表没用名称无法访问表中的字段

  • 例子:查询出2011年以后入职的员工信息,包括部门名称
    1.在员工表中查询2011-1-1以后入职的员工
SELECT * FROM emp WHERE join_date > '2011-1-1';

2.查询所有的部门信息,与上面的虚拟表中的信息组合,找出所有部门id等于的dept_id

SELECT * FROM dept d, (SELECT * FROM emp WHERE join_date > '2011-1-1') e WHERE e.dept_id = d.id;

三、总结

1.子查询的结果是单行单列(一个值情况), 一般放在where后面作为条件, 通过=,>,<,<>

select ... from ... where[=><<>...] (子查询) 

2.子查询的结果是单列多行, 一般放在where后面作为条件, 通过in

select ... from ... wherein (子查询) 

3.子查询的结果是多行多列, 一般放在from后面作为虚拟表, 需要给虚拟表取别名

select ... from (子查询) as 别名   where 条件

二、事务

一、解释

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

  • 操作: zs向李四转账100元
  • 组成单元: zs钱-100, ls钱+100
    • 操作成功: zs钱900,ls钱1100
    • 操作失败: zs钱1000,ls钱1000
    • 不可能发生: zs钱900,ls钱1000; zs钱1000,ls钱1100

二、事务的作用

保证一组操作全部成功或者失败。

三、MYSQL进行事务管理

  1. 自动事务(mysql默认)
  2. 手动开启一个事务
    自动事物一般是一条语句,直接完成,同步到数据库。
    手动开启,后续的操纵都是写到临时日志文件上面的,如果临时文件断开,临时文件会自动清空。commit会把操作同步到数据库中,rollback会把临时文件直接清空。

1、自动事务

一条sql语句就是一个事务

-- 场景: zs向ls转账100元
-- zs钱-100 ls钱+100
-- 自动事务管理: MySQL默认就是自动事务管理(自动开启事务,自动提交事务),一条sql语句就是一个事务
update account set money = money - 100 where name = 'zs';
-- 异常
update account set money = money + 100 where name = 'ls';

2.手动开启一个事物

start transaction;开启事务

​ commit;提交

​ rollback;回滚

-- 没有异常
start transaction; -- 开启事务
update account set money = money - 100 where name = 'zs'; -- zs钱-100
-- 没有异常
update account set money = money + 100 where name = 'ls'; -- ls钱 +100
commit; -- 提交事务


-- 有异常
start transaction; -- 开启事务
update account set money = money - 100 where name = 'zs'; -- zs钱-100
-- 有异常
update account set money = money + 100 where name = 'ls'; -- ls钱 +100
rollback; -- 回滚事务

第二种方式:设置MYSQL中的自动提交的参数
查看MYSQL中事务是否自动提交

show variables like '%commit%';

设置自动提交的参数为OFF

set autocommit = 0;-- 0:OFF  1:ON

3.回滚点

在某些成功的操作完成之后,后续的操作有可能成功有可能失败,但是不管成功还是失败,前面操作都已经成功,可以在当前成功的位置设置一个回滚点。可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称之为回滚点。回滚点不会结束事务。
3.1回滚点的操作语句

--设置回滚点
savepoint 名字

--回到回滚点
rollback 名字

3.2例子

  1. 将数据还原到1000

  2. 开启事务

  3. 让张三账号减3次钱

  4. 设置回滚点:savepoint three_times;

  5. 让张三账号减4次钱

  6. 回到回滚点:rollback to three_times;

总结:设置回滚点可以让我们在失败的时候回到回滚点,而不是回到事务开启的时候。

start transaction;
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
-- 以上sql语句没有问题
savepoint abc;
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
-- 出现异常,回滚到abc回滚点位置
rollback to abc;
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
update account set money = money - 100 where name = 'zs'; -- zs账户-100
commit;

3.3 应用场景

插入大量的数据的时候. 1亿条数据 需要插入很久. 要求: 1亿条数据是一个整体,要么全部插入成功的 要么都不插入成功.

四、事务特性和隔离级别

1.事物特性

  • 原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
eg: zs 1000; ls 1000; 
	zs 给 ls转100
	要么都发生zs 900; ls 1100;
	要么都不发生zs 1000; ls 1000;
  • 一致性(Consistency)事务前后数据的完整性必须保持一致.
eg: zs 1000; ls 1000;  一共2000
	zs 给 ls转100
	要么都发生zs 900; ls 1100; 	一共2000
	要么都不发生zs 1000; ls 1000; 一共2000
  • 持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
eg: zs 1000 给小红 转520, 张三 提交了
  • 隔离性(Isolation)事务的隔离性是指多个用户并发操作数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。 简单来说: 事务之间互不干扰
    如果不考虑隔离性,会引发下面的问题
并发访问问题含义
脏读一个事务读取到了另一个事务中尚未提交的数据
不可重复读一个事务中两次读取到的数据内容不一致,要求的是一个事务中多次读取时数据是一致的,这是事务update时引发的问题
幻读一个事务中两次读取的数据的数量不一致,要求在一个事务多次读取的数据的数量是一致的,这是insert或delete时引发的问题

2.事务隔离级别

可以通过设置事物隔离级别解决读的问题

2.1事务四个隔离级别
级别名字隔离级别脏读不可重复读幻读数据库默认隔离级别
1读未提交read uncommitted
2读已提交read committedOracle
3可重复读repeatable readMySQL
4串行化serializable

隔离级别越高,安全性越高,性能(效率)越差。

2.2设置隔离级别
set session transaction isolation level  隔离级别;
eg: 设置事务隔离级别为:read uncommitted,read committed,repeatable read,serializable
set session transaction isolation level read uncommitted;
2.3查询当前事务隔离级别
select @@tx_isolation;

3.总结

  1. 事务的特性
    • 原子性
    • 一致性
    • 持久性
    • 隔离性
  2. 不考虑隔离性会引出一些问题: 脏读, 不可重复读, 幻读
  3. 这些问题 可以 隔离级别解决

三、数据库安全性问题的例子

四、数据的备份和还原

在服务器进行数据传输、数据存储和数据交换,就有可能产生数据故障。比如发生意外停机或存储介质损坏。这时,如果没有采取数据备份和数据恢复手段与措施,就会导致数据的丢失,造成的损失是无法弥补与估量的。

1.备份数据库

mysqldump -u用户名 -p密码 数据库 > 文件的路径

2.还原格式

SOURCE 导入文件的路径

注意:还原的时候需要先登录MySQL,并创建数据库和选中对应的数据库

3.使用navicat备份和还原

右键选择数据库-结构和数据-进行备份

右键选择数据库-运行sql文件-进行还原

工作里面一般是运维在处理, 运维处理的话一般使用定时任务自动备份.

五、数据库设计三大范式

一、1NF

数据库表的每一列都是不可分割的原子数据项,不能是集合、数组等非原子数据项。即表中的某个列有多个值时,必须拆分为不同的列。简而言之,第一范式每一列不可再拆分,称为原子性

二、2NF

在满足第一范式的前提下,表中的每一个字段都完全依赖于主键。所谓完全依赖是指不能存在仅依赖主键一部分的列。简而言之,第二范式就是在第一范式的基础上所有列完全依赖于主键列。当存在一个复合主键包含多个主键列的时候,才会发生不符合第二范式的情况。比如有一个主键有两个列,不能存在这样的属性,它只依赖于其中一个列,这就是不符合第二范式。

简而言之,第二范式需要满足:

  1. 一张表只描述一件事情
  2. 表中的每一个列都依赖于主键
    如果不准守第二范式,数据冗余,相同数据无法区分。遵守第二范式减少数据冗余,通过主键区分相同数据。

三、3NF

在满足第二范式的前提下,表中的每一列都直接依赖于主键,而不是通过其它的列来间接依赖于主键。简而言之,第三范式就是所有列不依赖于其它非主键列,也就是在满足2NF的基础上,任何非主列不得传递依赖于主键。所谓传递依赖,指的是如果存在"A → B → C"的决定关系,则C传递依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系:主键列 → 非主键列x → 非主键列y

四、总结

1.列不可分割—1NF
2.不能产生局部依赖—2NF
3.不能产生传递依赖–3NF
记住: 一张表只描述一件事,每个列都不能分割,并且每个列都直接依赖主键

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值