【2】select语句的执行顺序
from--where -- group by– select - having- order by
【1】不相关的子查询引入:
不相关的子查询:子查询可以独立运行,先运行子查询,再运行外查询。
相关子查询:子查询不可以独立运行,并且先运行外查询,再运行子查询
【2】不相关的子查询优缺点:
好处:简单 功能强大(一些使用不相关子查询不能实现或者实现繁琐的子查询,可以使用相关子查询实现)
缺点:稍难理解
【3】sql展示:
-- 【1】查询最高工资的员工 (不相关子查询) select * from emp where sal = (select max(sal) from emp) -- 【2】查询本部门最高工资的员工 (相关子查询) -- 方法1:通过不相关子查询实现: select * from emp where deptno = 10 and sal = (select max(sal) from emp where deptno = 10) union select * from emp where deptno = 20 and sal = (select max(sal) from emp where deptno = 20) union select * from emp where deptno = 30 and sal = (select max(sal) from emp where deptno = 30) -- 缺点:语句比较多,具体到底有多少个部分未知 -- 方法2: 相关子查询 select * from emp e where sal = (select max(sal) from emp where deptno = e.deptno) order by deptno -- 【3】查询工资高于其所在岗位的平均工资的那些员工 (相关子查询) -- 不相关子查询: select * from emp where job = 'CLERK' and sal >= (select avg(sal) from emp where job = 'CLERK') union ...... -- 相关子查询: select * from emp e where sal >= (select avg(sal) from emp e2 where e2.job = e.job)
-- 多行子查询:一般设计多个表
-- 多行子查询: -- 【1】查询【部门20中职务同部门10的雇员一样的】雇员信息。 -- 查询雇员信息 select * from emp; -- 查询部门20中的雇员信息 select * from emp where deptno = 20;-- CLERK,MANAGER,ANALYST -- 部门10的雇员的职务: select job from emp where deptno = 10; -- MANAGER,PRESIDENT,CLERK -- 查询部门20中职务同部门10的雇员一样的雇员信息。 select * from emp where deptno = 20 and job in (select job from emp where deptno = 10) -- > Subquery returns more than 1 row select * from emp where deptno = 20 and job = any(select job from emp where deptno = 10) -- 【2】查询工资比所有的“SALESMAN”都高的雇员的编号、名字和工资。 -- 查询雇员的编号、名字和工资 select empno,ename,sal from emp -- “SALESMAN”的工资: select sal from emp where job = 'SALESMAN' -- 查询工资比所有的“SALESMAN”都高的雇员的编号、名字和工资。 -- 多行子查询: select empno,ename,sal from emp where sal > all(select sal from emp where job = 'SALESMAN'); -- 单行子查询: select empno,ename,sal from emp where sal > (select max(sal) from emp where job = 'SALESMAN'); -- 【3】查询工资低于任意一个“CLERK”的工资的雇员信息。 -- 查询雇员信息 select * from emp; -- 查询工资低于任意一个“CLERK”的工资的雇员信息 select * from emp where sal < any(select sal from emp where job = 'CLERK') and job != 'CLERK'
-- 单行子查询:不涉及多个表
-- 单行子查询: -- 查询工资高于平均工资的雇员名字和工资。 select ename,sal from emp where sal > (select avg(sal) from emp); -- 查询和CLARK同一部门且比他工资低的雇员名字和工资。 select ename,sal from emp where deptno = (select deptno from emp where ename = 'CLARK') and sal < (select sal from emp where ename = 'CLARK') -- 查询职务和SCOTT相同,比SCOTT雇佣时间早的雇员信息 select * from emp where job = (select job from emp where ename = 'SCOTT') and hiredate < (select hiredate from emp where ename = 'SCOTT'
CONCAT(str1, str2, ···, strn)
TRIM(str) 去除字符串str左右两侧的空格
CURDATE()
CURTIME()
NOW()
select curdate(),curtime() ; -- curdate()年月日 curtime()时分秒
IF(condition, t, f)
select empno,ename,sal,if(sal>=2500,'高薪','底薪') as '薪资等级' from emp; -- if-else 双分支结构
CASE
select empno,ename,sal, case when sal<=1000 then 'A' when sal<=2000 then 'B' when sal<=3000 then 'C' else 'D' end '工资等级', deptno from emp;
-- 手动开启事务: start transaction; update account set balance = balance - 200 where id = 1; update account set balance = balance + 200 where id = 2; -- 手动回滚:刚才执行的操作全部取消: rollback; -- 手动提交: commit;
当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
*不可重复度和幻读区别:*
不可重复读的重点是修改,幻读的重点在于新增或者删除。
*解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表*
例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。
例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读
事务的隔离级别用于决定如何控制并发用户读写数据的操作。数据库是允许多用户并发访问的,如果多个用户同时开启事务并对同一数据进行读写操作的话,有可能会出现脏读、不可重复读和幻读问题,所以MySQL中提供了四种隔离级别来解决上述问题。
事务的隔离级别从低到高依次如下,隔离级别越低,越能支持高并发的数据库操作
多事务方法之间调用,事务是如何管理
级别 | 解释 |
---|---|
PROPAGATION_Required | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择(默认)。 |
PROPAGATION_SUPPORTS (support) | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY(mandatory) | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW(required_new) | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED(not_supperted) | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER (never) | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED (nested) | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
问: 如果service层 add方法调用了 addDept和addEmp两个方法
答:
PROPAGATION_REQUIRED 如果add方法有事务,那么addDept和addEmp就加入到add方法里的事务 如果add方法没有事务,那么就新建一个事务,将addDept和addEmp加入到这个新的事务中
PROPAGATION_REQUIRES_NEW 无论add是否有事务,都建立一个新的事务,所有的方法都加入到新的事务中,add原来的事务就不用了
问: PROPAGATION_NESTED (nested) 与PROPAGATION_Required 区别
Required 是两个和并成一个事物,
nested 是两个事物
详细解释:
REQUIRED会跟着父任务一同提交,一同失败 。 而NESTED是 如果当前事务出现异常,本身进行回滚操作,但是父任务不会进行回滚操作 ,不过如果父任务发生异常,子任务会进行回滚操作
1) DEFAULT (默认)
这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
MySQL默认REPEATABLE_READ Oracle默认READ_COMMITTED
2) READ_UNCOMMITTED (读未提交)
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
READ_COMMITTED (读已提交)
保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
REPEATABLE_READ (可重复读)
这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
SERIALIZABLE(串行化)
这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。
事务是否只能读取数据库的数据,如果为true,则不允许进行增删改
当方法发生哪些异常时才会回滚
当方法发生哪些异常时,不会回滚
事务一定要在多长时间之内提交,如果不提交就会回滚