AVG --平均值
COUNT--返回不为空的记录总数
MAX--最大值
MIN--最小值
SUM--求和
select count(*) 员工数,sum(sal) 工资和,max(sal) 最高工资,min(sal) 最低工资,sum(comm)/count(*) 平均奖金,avg(comm) 平均奖金错 from emp
分组函数,会把null值的行排除在外(即分组函数会忽略空值null),因为comm中有空值,所以avg(comm)统计出来数据不对。
解决办法:
可以使用nvl来对包含空值列进行处理
select avg(nvl(comm,0)) 平均奖金 from emp;
COUNT(DISTINCT expr) 返回 expr非空且不重复的记录总数。
select count(distinct deptno) from emp;
不能在 WHERE 子句中使用组函数(注意)。
select * from emp where avg(sal)>2000(错误)
可以在 HAVING 子句中使用组函数。
select deptno from emp group by deptnohaving deptno=20;(正确)
使用group by 子句来进行分组数据,格式:
格式select 列1,统计函数1,统计函数n from 表名 where ... group by 列1,列2
注意:使用分组统计时,显示的列,必须是group by中的列名或者是分组统计结果,group by中有的列可以不显示。
select deptno, avg(sal) from emp group bydeptno; (正确)
select ename,deptno,avg(sal) from emp group by deptno;(错误,ename没有出现在group by子句中)
select deptno, avg(sal) from emp group bydeptno, job;(正确,只是没有显示job列)
groupby子句的增强:
rollup--函数应用。
group by null,不按任何条件下分组。
select deptno,job,sum(sal) from emp groupby rollup(deptno,job);(先按deptno分组再按job分组)
启用报表显示格式:breakon 列名 skip 1;
关闭报表格式:breakon null;
使用having子句可以过滤分组后的记录。格式:
select * from 表名 where ... group by 列名 having 分组限制条件(gorup by中的列名,分组统计函数)
对分组统计的结果进行排序。最后用使用order by语句.
在Order by中可以使用别名(因为是最后一步).//在where中不能使用别名(只能使用真实列名,因为他是第一步)
select deptno from emp group by deptnohaving deptno=20;(having中的条件只能是group by中有的列或分组函数)
当从多个表中查询时,如果省略连接条件,连接条件无效,所有表中的所有行互相连接都是出现笛卡尔积,笛卡尔积的记录数是两个表中的记录数的乘积。
为了避免笛卡尔集, 可以在 WHERE 加入有效的连接条件。
连接 n个表,至少需要 n-1个连接条件。 例如:连接三个表,至少需要两个连接条件。
1)按连接条件来分类:
A等值连接
select e.empno,e.ename,d.dname from empe,dept d where e.deptno=d.deptno;(查询员工所在的部门名称)
B非等值连接
select e.empno,e.ename,e.sal,s.grade fromemp e, salgrade s where e.sal between s.losal and s.hisal;(查询员工的工资级别)
2)按连接类型:
C内连接
内连接(等值,非等值连接)只有满足条件的记录才会出现在结果集中,null值的不会出现。
格式:表1[inner] join 表2 on 表1.xx = 表2.xx;
select e.empno,e.ename,d.dname from emp e innerjoin dept d on e.deptno=d.deptno;(inner可以省略)
D外连接(左外/右外/满(全)连接)
左外连接:(+号在右)
显示左边表的所有记录,不管是否为null值。
select e.empno,e.ename,d.dname from empe,dept d where e.deptno=d.deptno(+);
select e.empno,e.ename,d.dname from emp e left outerjoin dept d on e.deptno=d.deptno;
(outer可以省略)
右外连接:(+号在左)
显示右边表的所有记录,不管是否为null值。
select e.empno,e.ename,d.dname from empe,dept d where e.deptno(+)=d.deptno;
select e.empno,e.ename,d.dname from emp e right outerjoin dept d on e.deptno=d.deptno;
满(全)连接:
把连接条件两个表中的所有行均包括结果集中,满足连接条件就连在一起,不满足条件记录均单独占一行。
selecte.empno,e.ename,d.dname from emp e fulljoin dept d on e.deptno=d.deptno;
一个表与自己进行连接,可以把一张表看成表示不同的内容,比如emp即有员工信息,也有老板信息。
select e.empno,e.ename,e.mgr,m.ename from emp e,emp m where e.mgr=m.empno; (查询员工上司的名字)
子查询 (内查询) 在主查询之前一次执行完成。
子查询的结果被主查询使用 (外查询)。
主查询的select from where having 后都可以放子查询
不可以在主查询的groupby 放子查询
主查询和子查询可以不是用一张表,只要子查询返回的结果主查询可以使用,即可。
子查询要包含在括号内。
将子查询放在比较条件的右侧。
单行操作符对应单行子查询,多行操作符对应多行子查询。
A、在select语句后面的子查询要求,返回的记录只能是一行一列。
select e.ename,e.deptno,(select avg(sal) fromemp group by deptno) from emp e;(错误,返回多行)
B、在from后面放子查询
select * from (select * from dept);
C、前面是在where后面使用子查询
select * from emp where deptno in(select deptno from emp group by deptno having avg(sal)>2000);
D、 having可以放子查询
select deptno from emp group by deptno having avg(sal)>(selectavg(sal) from emp where deptno=20);
E、主查询和子查询可以不是用一张表,只要子查询返回的结果主查询可以使用,即可
select * from emp where deptno =(select deptno from dept wheredname='ACCOUNTING');
只返回一行记录,使用单行比较操作符如>,<,>=,=,<>。
select * from emp where sal>(select avg(sal) from empgroup by deptno);(错误子查询返回了多行,但使用的单行比较操作符)
select * from emp where sal>(select avg(sal) from emp);(正确)
如果子查询返回的null,则主查询查不到内容:
select * from emp where ename =(selectename from emp where name ='abc');(没有记录返回)
返回多行记录,使用多行比较操作符,如:
in等于列表中的任何一个
any和子查询返回的任意一个值比较
all和子查询返回的所有值比较
错误:select *from emp where deptno =(selectdeptno from dept where dname='ACCOUNTING' or dname='SALES');子查询返回多行
正确:
select * from emp where deptno in(select deptno from dept wheredname='ACCOUNTING' or dname='SALES');
select * from emp where deptno = any (select deptno from dept wheredname='ACCOUNTING' or dname='SALES');
大于all,表示大于最大的
大于any,表示大于最小的
select * from emp where sal > any(select sal from empwhere deptno=20);大于子查询结果中最小的就可以了。
查询是经理的员工信息
正确:select *from emp where empno in(select mgrfrom emp);
查询不是经理的员工信息
错误:select *from emp where empno not in(selectmgr from emp);----depnto not in (10,20)表示deptno<>10 and deptno<>20
使用not in的时候,子查询中返回的结果不要有null,否则得不到想要结果。
正确:select *from emp where empno not in(select mgr from emp where mgr is not null);
可以直接在返回的结果中包括这个rownum,是一个伪列,可以同过指定别名将其转为实列。
rownum 伪列,在表物理文件中是没有这一列,逻辑一列。每一次查询时候,都回重新计算一列。
注意1:
rownum是在where过滤后返回符合条件的结果生成的,第一个返回的为1,第二个为2...。
注意:先生成rownum,然后再进行order by操作。
注意2:
在rownum之前不能加上表的别名,如 from emp e whre e.rownum<=3,这是错误的。
注意3:
rownum不能进行大于运算。他必须先取前面的数据,取完前面才能取后面的。
select * from emp where rownum >=3; (没有结果返回)
语法:
SELECT [column_list], ROWNUM
FROM (SELECT [column_list]
FROM table
ORDER BY Top-N_column)
WHERE ROWNUM <= N;
查询前几条符合条件的记录:(工资最高的前三条记录)
select rownum, e.* from (select * from emporder by sal desc) e where rownum<=3;
工资最高的第3到第5条记录:
select * from (selectrownum r,e.* from (select * from emp order bysal desc) e where rownum<=5) where r>=3;(效率高一些)
select * from (select rownum r,e.* from(select * from emp order by sal desc) e) wherer >=3 and r<=5(效率低一些)
A、[10,20,30]
B、[30,40,50]
UNION 两个集合中元素加到一起,重复的只保留一个. A Union B=[10,20,30,40,50]
UNION ALL 两个集合中元素加到一起,重复也保留。A union all B=[10,20,30,30,40,50]
INTERSECT 交集,取两个集合中都有的元素。AINTERSECT B=[30]
MINUS 差集,取A集合中有,但B集合中没有元素。 A MINUS B=[10,20] B MINUS A=[40,50]
A. 参与运算的各个集合必须列数相同,且类型一致
B. 结果集采用第一个select的表头作为表头
C. 如果要排序,order by 必须在运算的最后面
select deptno,job,sum(sal) from emp groupby deptno,job
+
select job,sum(sal) from emp group bydeptno
+
select sum(sal) from emp group by null
select deptno,job,sum(sal) from emp groupby rollup(deptno,job)
等于下面的语句:
select deptno,job,sum(sal) from emp groupby deptno,job
UNION
select deptno,to_char(null),sum(sal) fromemp group by deptno
UNION
selectto_number(null),to_char(null),sum(sal) from emp group by null
order by deptno
DML语言可以用来向表中插入数据,修改现存数据,删除现存数据。
insert-添加数据
update-更新数据
delete--删除数据
查询:select
事务是由一组DML语句组成的。
删除语句delete(一条一条的删除,可回滚)
清空表:truncatetable(摧毁表,再重建,不可回滚)
他上一条DDL语句,他会整个表全删除掉,重建表。 他不会在事务中,内容不能rollback.
清空表: 效果上 truncate table == delete fromtable
区别:
1. delete 逐条删除记录;truncate 摧毁表,再重建
2. delete 不会释放空间; truncate释放
3. delete 可能产生碎片; truncate不会
4. delete可以闪回(可以撤销); truncate不会
数据库事务由以下的部分组成:
一个或多个DML 语句
一个 DDL(DataDefinition Language – 数据定义语言) 语句
一个 DCL(DataControl Language – 数据控制语言) 语句
事务开始:以第一个 DML 语句的执行作为开始
事务结束:
显示结束: commit rollback
隐式结束(自动提交): 执行了DDL语句或DCL语句, exit(事务正常退出)
隐式回滚(系统异常终了): 关闭窗口,死机,掉电
使用 SAVEPOINT 语句在当前事务中创建保存点。(savepoint A)
使用 ROLLBACK TOSAVEPOINT 语句回滚到创建的保存点。(rollbackto A)
事务正常提交后,所有保存点被释放。
l 对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制,就会导致各种并发问题:
• 脏读: 对于两个事物 T1, T2,T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若T2 回滚, T1读取的内容就是临时且无效的.
• 不可重复读: 对于两个事物 T1, T2,T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
• 幻读: 对于两个事物 T1, T2,T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
l 数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.
l 一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱
l Oracle 支持的 2 种事务隔离级别:READ COMMITED, SERIALIZABLE. Oracle 默认的事务隔离级别为: READ COMMITED
l Mysql 支持 4 中事务隔离级别. Mysql 默认的事务隔离级别为: REPEATABLE READ