一、高级查询
(一)关联查询
(A)内连接
- 1.只有在连接表都存在的记录才能被连接展示在最终结果集中。
- 2.连接后结果条目与连接顺序无关。只是表结构不同
###########################内连接#############################
-- -- 连接查询
#ename (emp) dname (dept)
#查询所有员工的姓名和所在部门的名称
#方法一:
select * from emp , dept where emp.deptno = dept.deptno;
#方法二:inner join
select * from emp inner join dept on emp.deptno = dept.deptno;
#方法三:只适合连接属性的名称相同的情况
select * from emp inner join dept using (deptno);
################################################################
(B)外连接
(a)左外连接 left [outer] join …… on ……
(b)右外连接 right [outer] join …… on ……
- 执行策略:以主表为基准,依次在从表中获取和主表相匹配的记录。如果找到,则连接并展示在结果中,如果找不到。以null填充。
- 外连接与连接顺序有关,左外连接是前主后从,右外连接是前从后主。
select * from dept
left join emp
on emp.deptno = dept.deptno;
(C)自然链接
自然连接即等值连接:找到字段一样并且值一样的,进行连接
select * from emp nuatual join dept;
(二)子查询(嵌套查询)
将子查询的结果作为另一个查询的条件或结果。
#查询工资大于SCOTT的所有员工信息
select * from emp where sal > (select sal from emp where ename ='scott');
(A)单行子查询(>,<,=)
select * from emp where sal > (select sal from emp where ename = 'SCOTT');
(B)多行子查询(只能用in, any ,all, exist)
- =any:in,
- >any:大于最小值
select * from emp where job in (select distinct job from emp where deptno = 30);
关联查询和子查询综合例子
##########################################################
#练习
#1.查询员工编号为7788的员工姓名和所在部门的名称
select ename,dname from emp,dept where dept.deptno = emp.deptno and empno = 7788 ;
#2.查询所有的 部门名称和该部门下的员工信息
#重复字段需声明表名
select dept.deptno , emp.* from dept left join emp on dept.deptno = emp.deptno;
#3.查询员工姓名和其领导的姓名
#领导编号与姓名也在同一张表中查(自连接):起别名。
select e1.ename,e2.ename from emp e1, emp e2
where e1.mgr = e2.empno;
#再起别名
select e1.ename yuangong,e2.ename lingdao from emp e1, emp e2
where e1.mgr = e2.empno;
#查询工资大于SCOTT的所有员工(单行子查询>,<,=)
select * from emp where sal > (select sal from emp where ename = 'SCOTT');
#查询和30号部门的所有员工职位相同的员工的信息。(多行子查询,只能用in, any ,all)
select * from emp where job in (select distinct job from emp where deptno = 30);
#查询大于所在部门平均工资的员工信息
select emptno,avg(sal) from emp group by deptno ;
#1.关联查询
select emp.* from emp,(select deptno,avg(sal) avg from emp group by deptno) e where emp.deptno = e.deptno and emp.sal > e.avg;
#2.子查询
select * from emp e1 where sal >
(select avg(sal) from emp e2 where e2.deptno = e1.deptno);
1.主查询遍历将Deptno值传给子查询;
2.子查询根据主查询传输的deptno值获取对那个部门的平均工资;
3.将查询结果返回给主查询
4.主查询根据子查询的返回结果实现查询
#查询工资>2000的员工所处的部门信息
#方法一
#1.查询工资>2000的员工的部门编号
#2.根据部门编号查询部门信息
select * from dept where deptno in (select deptno from emp where sal>2000);
#方法二exists;
#先执行主查询,将主查询的记录依次在子查询中根据通用列实现匹配。
#如果匹配列,子查询返回true。将主查询的结果与子查询连接展示在结果集中。
#如果不能匹配,则传入子查询的主查询记录不会出现在结果集中。
select * from dept d where exists
(select * from emp e where sal>2000 and d.deptno = e.deptno);
select * from dept where exists
(select * from emp where sal>2000 and dept.deptno = emp.deptno);
##############################################################################
#关联查询与子查询的选择:
# 结果集中字段分布于多张表时,用子查询是做不出来的。
#关联查询通用性强,既可以查询结果分布于多张表的情况也可以查询结果位于单张表的情况。
#不过单张表上子查询快些。
#1.查询工资高于30号部门最高工资的非30号部门的员工信息
select * from emp where deptno != 30 and (sal> (select max(sal) from emp where deptno = 30 group by deptno));
select * from emp where sal > all (select sal from emp where deptno = 30) and deptno <>30;
select * from emp
#2.查询30号部门中工资次高的员工信息
select * from emp where deptno = 30 order by sal desc limit 1,1 ;
#3.查询工资大于30号部门平均工资并且不在30号部门的员工信息和所在部门信息。
select * from dept d,
(select * from emp where sal> (select avg(sal) from emp where deptno = 30 ) and deptno <>30) e
where d.deptno = e.deptno;
#4.查询各个部门中工资最低的员工信息
#fangfayi :关联查询
selct * from emp e ,
(select deptno ,min (sal) min from emp group by deptno ) e1
where e.deptno = e1.deptno and e.sal = e1.min;
#方法二:子查询
select * from emp e where exists
(select deptno,min(sal) min from emp group by deptno having min = e.sal);
############################################################################
(三)联合查询
union 去重 union all 不去重。
#关键字union,union all
#union 去重,union all 不去重
-- 查询工资>2000或者在20号部门的员工信息。
select * from emp where sal>2000
union
select * from emp where deptno = 20;
二、事务
(一)存储引擎:
Mysql的核心就是存储引擎。
增删改查操作通过存储引擎实现。
Mysql中可以有多种存储引擎,5.5后默认使用InnoDB。
InnoDB是事务型的存储引擎。
(二)事务
(A)什么是事务?
事务用于保证数据的一致性,由一组DML操作组成,该组SQL语句要么同时成功,要么同时失败。例如转账。
(B)事务的四个特性(ACID):
(a)原子性:事务的一组DML操作必须作为整体执行,不可分割;
(b)一致性:事务执行前后整体的状态必须一致;
(c)隔离性:并发事务只见那互相不能影响;
(d)持久性:事务执行完毕就永久保存。
(三)并发引发的问题
(A)脏读:一个事务读到另一事务未提交的数据
(B)不可重复读:
- 一个事务在多次读取过程中发现数据不一致性;
- 该事务在多次读期间,由另一个事务修改并进行事务提交引起;
(C)幻读:一个事务在读取过程中,发现数据变多或者消失。
- 在该事务多次读取期间,由另一个事务添加或删除记录,并提交事务引起。
(四)事务的隔离级别
(A)读未提交:快,但不能解决任何一个问题,基本不用;
(B)读已提交:能解决脏读问题,用的较多;
(C)可重复性:解决脏读和不可重复度问题,用的较多;
(D)串行化:解决所有问题,直接加锁,必须一个一个来。速度太慢,基本不用。
- Mysql支持以上四种,Oracle只支持(B)和(D)。
(五)编程实现事务管理
示例:
#################################事务######################################
create table account (
sid int,
sname varchar(20),
acount int
);
show variables like '%autocommit%'
set autocommit = 0; #关闭自动提交
start Transaction ; #开启事务
insert into account values (1,'张三',100),(2,'李四',200);
update account set acount = 90 where sname = '张三';
commit;#提交
rollback;#回滚
set autocommit = 1; #关闭自动提交
###################################################################