Oracle学习笔记(2)

1.   分组函数

1.1基本应用

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;(正确)

1.2分组数据

使用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;

1.3过滤分组

使用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中有的列或分组函数)

2.   多表连接查询

2.1笛卡尔积

当从多个表中查询时,如果省略连接条件,连接条件无效,所有表中的所有行互相连接都是出现笛卡尔积,笛卡尔积的记录数是两个表中的记录数的乘积。

为了避免笛卡尔集, 可以在 WHERE 加入有效的连接条件。

2.2连接概述

连接 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;

3)自连接

一个表与自己进行连接,可以把一张表看成表示不同的内容,比如emp即有员工信息,也有老板信息。

select e.empno,e.ename,e.mgr,m.ename from emp e,emp m where e.mgr=m.empno; (查询员工上司的名字)

3.   子查询

3.1概述

子查询 (内查询) 在主查询之前一次执行完成。

子查询的结果被主查询使用 (外查询)。

主查询的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');

3.2单行子查询

只返回一行记录,使用单行比较操作符如>,<,>=,=,<>。

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');(没有记录返回)

3.3多行子查询

返回多行记录,使用多行比较操作符,如:

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);大于子查询结果中最小的就可以了。

3.4关于null值的处理

查询是经理的员工信息

正确: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);

4.   Top N 分页

4.1 rownum概述

可以直接在返回的结果中包括这个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; (没有结果返回)

4.2 Top N的使用

语法:

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;

 

4.3分页 取N到M条符合条件的结果

工资最高的第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(效率低一些)

 

 

5.   集合

5.1集合概述

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]

5.2集合运算注意问题:

A. 参与运算的各个集合必须列数相同,且类型一致

B. 结果集采用第一个select的表头作为表头

C. 如果要排序,order by 必须在运算的最后面

5.3使用集合代替group by rollup

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

6.   数据操作语言DML

6.1 DML语句概述

DML语言可以用来向表中插入数据,修改现存数据,删除现存数据。

insert-添加数据

update-更新数据

delete--删除数据

查询:select

事务是由一组DML语句组成的。

6.2 delete和truncate的区别

删除语句delete(一条一条的删除,可回滚)

清空表:truncatetable(摧毁表,再重建,不可回滚)

他上一条DDL语句,他会整个表全删除掉,重建表。 他不会在事务中,内容不能rollback.

清空表: 效果上 truncate table == delete fromtable

区别:

1. delete 逐条删除记录;truncate 摧毁表,再重建

2. delete 不会释放空间; truncate释放

3. delete 可能产生碎片; truncate不会

4. delete可以闪回(可以撤销); truncate不会

7.Oralce中的事务

7.1概述

数据库事务由以下的部分组成:

一个或多个DML 语句

一个 DDL(DataDefinition Language – 数据定义语言) 语句

一个 DCL(DataControl Language – 数据控制语言) 语句

事务开始:以第一个 DML 语句的执行作为开始

事务结束:

显示结束:  commit rollback

隐式结束(自动提交):  执行了DDL语句或DCL语句, exit(事务正常退出)

隐式回滚(系统异常终了):  关闭窗口,死机,掉电

7.2保存点

使用 SAVEPOINT 语句在当前事务中创建保存点。(savepoint A)

 

使用 ROLLBACK TOSAVEPOINT 语句回滚到创建的保存点。(rollbackto A)

事务正常提交后,所有保存点被释放。

7.3数据库的隔离级别

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

 

你可能感兴趣的:(数据库,oracle,null,delete,数据库,语言,报表)