首页 > 代码库 > Oracle基本语法&&函数&&子查询&&分页查询&&排序&&集合操作&&高级分组函数

Oracle基本语法&&函数&&子查询&&分页查询&&排序&&集合操作&&高级分组函数

一.  数据库

手工---文件管理---数据库

DB:Database 数据库。

DBMS:管理数据库的软件。(oracle)

主流关系数据库:

1.      Oracle

2.      DB2

3.      SQL Server 基本没人使

4.      MySQL  基本没人用,免费

 

Linux 开源,可以发现漏洞补上

Windows服务器会有补丁,数据易泄漏

eclipse 日食

 

数据表(Table):

表的行(Row):记录

表的列(Column):字段

        

二.  关系型数据库

一对一:A表的一条记录对应B表的一条数据

一对多: A表的一条记录对应B表的多条数据

多对多:A表的多条记录对应B表的多条记录

三.  结构化查询语言

SQL(Stryctured Query Language)

 

INSERT 一条新纪录的时候,数据库会启动一个事物TRANS BEGIN

UPDATE                                         

DELETE                                          

INSERT

COMMIT  之后才会进行插入    TRANS FINISH

UPDATE                                         

DELETE                                          

INSERT

ROLLBACK  之前的操作无效,回滚到事物之前

四.  Oracle数据类型

NUMBER数据类型实例

CREATE  TABLE  student(id NUMBER(4),nameVARCHAR2(20),genderCHAR(1),fee NUMBER(7,2));

如果NUMBER后面没哟精度则默认为0

CHAR

直接表示字符串,最大长度是2000字节

设置固定长度如果写不满的话会补满空格

VARCHAR2

最大长度是4000字节,只有oracle中才会有varchar2

如果写不满的话后面就不补空格

变长

DATE

         用于定义日期时间的数据

         长度是7个字节

         默认格式是:DD-MON-RR,例如:11-APR-71

        

sql出过8和92版本

无论后面怎么改变,VARCHAR2始终不会改变,如果改变的话只改变VARCHAR

 

--创建表

CREATE TABLE employee(

  idNUMBER(4),

 name VARCHAR2(20),

 gender CHAR(1),

 birth DATE,

 salary NUMBER(6,2),

  jobVARCHAR2(30),

 deptno NUMBER(2)

);

 

--查看表结构

DESC employee;

 

--删除表

DROP TABLE employee;

 

数据库中字面量数字不需要用单引号,但是字符串需要单引号没有双引号

NOT NULL 和 DEFAULT 不能同时使用,DEFAULT不给值得时候才会赋值,给值的时候就用给的值

--设置非空和初始属性

CREATE TABLE employee(

  idNUMBER(4),

 name VARCHAR2(2) NOT NULL,

 gender CHAR(1) DEFAULT ‘M‘,

 birth DATE,

 salary NUMBER(6,2) DEFAULT 5000,

  jobVARCHAR2(30),

 deptno NUMBER(2)

);

--数据库中所有字段的默认值都是null,当插入数据的时候,某个字段没有给值得时候,则会将null值作为该字段的值,可以通过DEFAULT关键字为指定的字段设置一个指定的默认值DEFAULT ‘ ‘,对于字符串的字面量而言,在数据库中是使用单引号括起来的,SQL语句不区分大小写,但是字面量的值是区分大小写的。

修改表(表名和结构)

--修改表

--1.修改表名

--2.修改表结构

1.    RENAMEemployee to myemp;

DESC myemp;

2.     

--2.1添加一个新字段

--添加的字段只能在末尾

ALTER TABLE myemp ADD(

 hiredate DATE DEFAULT SYSDATE,

 application VARCHAR2(60) NOT NULL

);

DESC myemp;

--2.2修改表中现有字段

--修改只能修改字段的类型,长度,默认值以及是否为空,该操作不建议子啊表中已经含有数据的情况下

--进行修改,否则有可能修改不成功。例如:尽量不修改字段类型,修改长度,尽量增加而不是减少

ALTER TABLE myemp MODIFY(

  jobVARCHAR2(40)

);

DESC myemp;

 

DML语句

--DML语句

--对表中数据进行操作 包含:增删改操作  DML是伴随事物操作的

--INSERT语句

--向表中插入数据

INSERT INTO myemp(id , name ,job,deptno)VALUES (1,‘jack‘,‘CLERK‘,10);

SELECT * FROM myemp;

//切记不要随便commitrollback;

--全列插入

INSERT INT myemp VALUES(...);

不建议全列插入

 

--插入日期建议使用内置函数

--TO_DATE,当然也可以使用字符串,但是格式必须遵守DD-MM-RR,由于语言差异不建议使用

DESC myemp;

INSERT INTO myemp(id,name,job,birth) VALUES(6,‘王莹‘,‘wif‘,TO_DATE(‘1995-10-18‘,‘YYYY-MM-DD‘));

 

 

--UPDATE

--修改表中的数据

UPDATE myemp SET gender = ‘F‘ WHERE id=2;

UPDATE myemp SET salary = 7000 , deptno=6WHERE gender=‘M‘;

--DELETE

--删除表中数据

DELETE FROM myemp where id=6;

UPDATE与DELETE通常都需要添加WHERE条件,否则就是对表中所有数据进行操作

TRUNCATE

TRUNCATE      TABLE  …直接删除整个表,不可回滚

DDL不受事物控制

 

一.  数据库基础(函数)

TCL                                事物控制

字符串类型:

char 和 varchar2

char存不满补满

char(2000 个英文字符 1000个汉字)  varchar2(4000个英文字符 2000个汉字(GBK))  数字是字节 BYTE

char长度不指定长度就是1,varchar2必须写

 

LONG和CLOB类型

LONG:varchar2加长版,存储变长字符串,最多达2GB字符串数据

一个表中只能有一个LONG类型列,不能作为主键,不能建立索引,不能出现在查询条件中

CLOB:存储定长或变长字符串,最多达4GB的字符串数据

Oracle 建议使用CLOB代替LONG

 

--CONCAT函数:连接字符串:只能拼接两个

select concat(ename,sal)

from emp

把ename和sal放在一列显示出来

select concat(concat(ename,‘:‘),sal)

from emp

||相当于+

select ename||‘:‘||sal

from emp

 

LENGTH:用于返回字符串的个数

如果是varchar2,返回实际长度

如果是char,长度还要包括后面空格

select ename,LENGTH(ename)

from emp

 

select ename

from emp

where LENGTH(ename)=4

 

//UPPER&&LOWER&&INITCAP

dual:伪表,一般测试函数时候用的

当查询的内容不是任何表中数据时,可以用伪表代替

selectUPPER(‘helloworld‘),LOWER(‘HELLOWORD‘),INITCAP(‘HELLO WORLD‘)

from dual

INITCAP两个单词的话每个单词首字母都是大写

 

TRIM&&LTRIM&&RTRIM

select

trim(‘e‘ from ‘eeeeeliteeee‘)

from dual

select

ltrim(‘estetsettesseltliteeee‘,‘est‘)

from dual

select

rtrim(‘estetsettesseltliteeee‘,‘est‘)

from dual

类似于正则,只要有est其中之一就删除

 

//LPAD&&RPAD

补位函数:在位数不足的时候使用

select ename,LPAD(sal,6,‘$‘)

from emp

左边补位$

RPAD右边不足的时候补右边$

如果中间参数为3的时候,无论sal用LPAD或者RPAD都从左往右截取3位

select ename,LPAD(sal,6,‘  ‘)

from emp

 

//SUBSTR截取字符串

select substr(‘thinking in java‘,10,2)

from dual

从第十位开始截取两个字符,oracle下标从1开始

select substr(‘thinking in java‘,-7,2)

from dual

从倒数第7位开始截取两位

最后一个取位数的参数是不可以写负数,取得位数必须为正值

 

//INSTR返回子串在原字符串的位置

--INSTR(str1,str2,m,n)

--查找str2在str1中的位置

--m、n可选

--m:从第几个字符开始查找

--n:出现几次

select

instr(‘thinking in java‘,‘in‘,1,3)

from dual

从第一位查找,出现的第三次

 

//ROUND

--ROUND(m,n):四舍五入

--保留m到小数点后的n位

--n为0或不指定这是保留到整数

--n为负数这是保留到小数点前的位数

select round(45.678,2)from dual

select round(45.678,0)from dual

select round(45.678,-1)from dual

 

//TRANC(m,n)

--TRANC(m,n):截取数字

--参数与ROUND一致

select TRUNC(45.678,2)from dual

select TRUNC(45.678,0)from dual

select TRUNC(45.678,-1)from dual

 

//MOD(m,n)

--MOD(m,n):求余

select * from emp

select ename,sal,MOD(sal,1000)

from emp

 

//CEIL&&FLOOR

--CEIL,FLOOP:向上去整数,向下去整数

select CEIL(45.678) from dual

SELECT FLOOR(45.678) FROM DUAL

 

二.  日期类型

--日期相关操作

--关键字

--sysdate:对应数据库一个内置函数,返回一个DATE类型的值,该值表示当前系统时间

--systimestamp:返回当前系统时间的时间戳类型

select sysdate from dual

select systimestamp from dual

 

日期转换函数

--TO_DATE()可以将一个字符串按照给定的日期格式解析为一个DATE类型的值

select to_date(‘2008-08-0820:08:05‘,‘YYYY-MM-DD HH24:MI:SS‘)

from dual

时分秒默认不显示

select to_date(‘2008年08月08日‘,‘YYYY"年"MM"月"DD"日"‘)

from dual

格式字符串中有除了英文,符号,数字之外的例如年月日需要用双引号括起来

--TO_CHAR():

--将日期按照指定的格式转换为字符串

select to_char(sysdate,‘YYYY-MM-DDHH24:MI:SS‘)

from dual

select to_char(sysdate,‘YYYY"年"MM"月"DD"日"HH24:MI:SS‘)

from dual

 

年份RR和YY的区别

User

YYtodate为92,转化为to_char的时候YYYY会根据当前系统世纪变为2092













Sys

下世纪

上世纪

本世纪

本世纪

50-99

0-49

50-99

0-49

把字符串转换为年的时候使用:

selectto_char(to_date(‘49-08-01‘,‘RR-MM-DD‘), ‘YYYY-MM-DD‘)

from dual

 

//LAST_DAY

select last_day(sysdate) from dual

 

//LAST_MONTHS

--对给定日期加上指定月,若i为负数,则为减肥

select ename,ADD_MONTHS(hiredate,12*20) as"入职20周年年纪念日" from emp

 

//MONTHS_BETWEEN(date1,date2)

--计算两个日期之间相差的月,计算使用date1-date2

selectename,months_between(sysdate,hiredate) from emp

 

//NEXT_DAY

--返回给定日期第二天开始一周内的周记的日期,i表示周记:  1为周日,2为周一,以此类推

select next_day(sysdate,6) as "下周五"from dual

 

//LEAST&&GREATEST

--求最小值与最大值

--参数至少一个

selectleast(sysdate,to_date(‘2008-10-10‘,‘YYYY-MM-DD‘)) from dual

select greatest(sysdate,to_date(‘2008-10-10‘,‘YYYY-MM-DD‘))from dual

 

//EXTRACT

--提取指定日期中指定时间分量的值

--date可以提取年月日,时间戳可以提取时分秒

select extract(year from sysdate) from dual

select ename,sal,hiredate

from emp

where extract(year from hiredate)=1982

 

三.  NULL的含义

就是空值

update student set gender= ‘M‘ where genderis null

判断状态是否是null的时候要用is不能用=,不为null的时候用 is not

 

--NULL与字符串连接,等于什么都没做

--NULL与数字计算,结果还是NULL

select ename,sal,comm,sal+comm from emp

select ename,comm,ename||comm from emp

--空值函数

--NVL(a1,a2)

--若a1位NULL则函数返回a2,否则返回a1自身,所以该函数的作用是将NULL值替换为非NULL值

select ename,sal,comm,sal+NVL(comm,0) fromemp

 

--NVL2(a1,a2,a3)

--当a1不为null时,返回a2

--a1为null时,返回a3

select ename,comm,NVL2(comm,‘有奖金‘,‘没有奖金‘) fromemp

 

一.  SQL查询语句

//使用别名

--当一个select子句中的一个字段是一个函数或者表达式时,那么结果集中对应的该字段的名字

--就是这个函数或表达式,可读性差,这时可以为该字段指定别名

select e.ename,e.sal*12 (as) "年薪",to_char(e.hiredate,‘YYYY-MM-DD‘)as "雇佣日期" from emp e

select ename,sal*12 sal,to_char(hiredate,‘YYYY-MM-DD‘)hiredate from emp

Oracle中统一不加as,可选加,如果要是加了双引号,字段就显示双引号中内容,就是可以实现字段的小写或者是汉字

 

//WHERE子句

--WHERE在查询中是用来添加过滤条件的

--它的过滤时机是在查询表中进行的,每当遍历表中一条数据时就会检查其是否满足WHERE条件

--满足则会被查询出来,不满足则忽略

 

//字符

         不能于      <>                       在Oracle中等同于!=

        

         //AND&&OR

         AND优先级高于OR

         可以用括号提高优先级

        

         //LIKE(模糊查询)

         --LIKE用于模糊匹配字符串,支持两个通配符

--_:表示任意的字符

--%:表示任意个字符
        

//IN&&NOT IN

--IN和NOT IN 是判断是否在列表中或者不能再列表中

--IN和NOT IN 通常用作子查询

select * fromemp

where job not in(‘MANAGER‘,‘CLERK‘)

 

//BETWEEN…AND…

--判断是否在一个范围内

select ename,salfrom emp

where salbetween 1500 and 3000

 

//使用ANYALL

--> ANY(list)大于最小

--< ANY(list)小于最大

--> ALL(list)大于最大

--< ALL(list)小于最小

--ANY与ALL是用作判断一个值是否>,>=,<,<=列表中的内容

 

//DISTINCT关键字

--用于将结果集中指定的字段的重复记录去除,DISTINCT应当紧跟在SELECT关键字之后,可以对单列去重也可以对多列去重

--多字段去重,不保证每个字段没有重复值,结果集中这些字段值得组合没有重复记录

select distinct job,deptnofrom emp

 

//ORDER BY 排序

--ORDER BY子句可以将当前结果集按照给定的字段进行升序或者降序排列

--ORDER BY 子句只能写在DQL语句的最后一个子句上

--ASC:升序 默认升序

--DESC:降序

--NULL在排序中被视为最大值

selectename,sal,deptno from emp

order by salDESC

         selectename,deptno,sal

from emp

order by deptnoDESC ,sal ASC

排队优先级按照第一个字段排序,当第一个字段有重复的时候才会按照第二个排

每个字段都需要单独指定排列方式

        

--聚合函数,又称多行函数,分组函数,聚合函数是用来统计的,可以将多条记录中的指定字段进行统计,然后又得到一个结果,聚合函数都自动忽略NULL

//MAX(),MIN()

selectmax(sal),min(sal) from emp

 

//AVG,SUM()

selectround(avg(sal)),sum(sal)  from emp

 

         //COUNT()统计记录数

         selectcount(*) from emp

         selectsum(comm),avg(comm) from emp

selectround(avg(NVL(comm,0)),2) from emp        

        

         //GROUP BY子句一般和聚合函数一起用

         --GROUPBY可以将当前查询的结果集按照GROUP BY子句给定的字段的值,

--相同的记录划分为一个组,配合聚合函数可以进行更细分的统计工作

         selectround(avg(sal)),deptno

from emp

group by deptno

--当SELECT子句中出现了聚合函数,那么凡不在聚合函数中的其他字段必须出现在GROUP BY子句中

--反过来着不是必须的,通常不使用聚合函数就没必要使用GROUP BY

         selectcount(*),job,deptno

from emp

group byjob,deptno

        

--WHERE中不允许使用聚合函数,原因在在于过滤时机不对,聚合函数的统计是建立在结果集的基础之上的这就说明在统计前,数据应当已经查询出来并生成了结果集,而WHERE的过滤就是在查询生成结果集的过程中进行的,所以WHERE在前统计在后,所以不能在WHERE中使用聚合函数进行过滤

        

         //HAVING用来过滤某些分组

--HAVING子句可以使用聚合函数的结果进行过滤,HAVING是配合GROUP BY 分组的,目的是根据过滤条件取舍某些分组的记录,HAVING必须跟在GROUP BY之后,不能单独定义

select avg(sal),deptno

from emp

group by deptno

havingavg(sal)>2000

//实现平均工资大于2000部门的最高工资和最低工资

selectmax(sal),min(sal)

from emp

group by deptno

havingavg(sal)>2000

 

查询语句执行顺序

1.      FROM子句 从后往前,从右往左,数据量较少的尽量放在后面

2.      WHERE子句

3.      GROUP BY

4.      HAVING

5.      SELECT      少写*

6.      ORDER BY

 

 

二.  SQL关联查询

不添加连接条件会产生笛卡尔积,笛卡尔积的记录数数参与关联查询的标的记录数的      积会将表的一条记录与另一张标的每条记录链接一次并产生一条记录

select e.ename,d.dname from emp e,dept d

通常N张表关联查询就要有至少N-1个连接条件

 

 

       内连接也是关联查询的一种,不满足连接条件的记录是不会出现在结果集中的

        lect e.ename,d.loc

from emp e

join dept d

one.deptno=d.deptno

where d.loc=‘NEWYORK‘

--外链接

--外连接在进行关联查询时除了会将满足连接条件的记录列出来,也会将不满足连接条件的就列出来

 

--外连接分为

--左外连接:以JOIN左侧表尾驱动表,该表中所有记录要显示出来,右侧表都为NULL

--右外连接:以JOIN右侧表尾驱动表,该表中所有记录要显示出来,左侧表都为NULL

--全外连接

selecte.ename,d.loc

from emp e

left outer joindept d

one.deptno=d.deptno

 

--自连接

--自连接保存的数据是当前表的一条记录

--可以对应当前表的多条记录

--这种设计用于结局记录属性相同但记录但又存在上下级关系的树状结构时使用

select e.ename ,m.ename,d.loc

from emp e

join emp m

on m.empno =e.mgr

join dept d

on e.deptno =d.deptno

wheree.ename=‘SMITH‘

一.  子查询

--子查询也是一条查询语句,只是它嵌套在其他SQL语句之中,作用是为外层SQL提供数据

SELECT ename,sal

FROM emp

WHERE sal>(SELECT sal FROM emp WHERE ename = ‘CLARK‘)

子查询创建表的时候有函数或者表达式要写别名

 

--DDL中使用子查询

--基于一个子查询的结果集快速创建一张表

create tablemyemployee as

select e.empno,e.ename,e.job,e.deptno,d.dname,d.loc

from emp e ,deptd

wheree.deptno=d.deptno(+)

         加号放在右面表示左外连接放在右面表示右外连接

        

--DML中使用子查询

--将SMITH部门所有员工工资提高百分之10

update emp

set sal = sal *1.1

where deptno =(select deptno from emp where ename=‘SMITH‘)

//搜索出有SALESMAN的部门,并且部门的工作不是SALESMAN的员工

selectename,job,deptno

from emp

where deptno in(select deptno from emp where job=‘SALESMAN‘)

andjob<>‘SALESMAN‘

//查询出比CLERJ,SALESMAN最大工资的工资

select ename ,sal ,job from emp

where sal >all(select sal from emp where job in (‘CLERK‘,‘SALESMAN‘))

 

IN\ALL\ANY 一般配合子查询使用

 

//EXISTS关键字

--EXISTS后面要跟一个子查询,当该子查询可以肇事奥查询出一条记录时,EXISTS返回真,not exists

--是相反操作

SELECTdeptno ,dname

FROM deptd

WHEREEXISTS(

  SELECT * FROM emp e

  WHERE e.deptno = d.deptno

)

 

 

//HAVING中使用子查询

--查看最低薪水高于30号部门最低薪水的部门

selectmin(sal),deptno from emp

group by deptno

having min(sal)>(select min(sal) from emp whereemptno=30)

 

//子查询在FROM

--多列子查询常被当做一张表看待而出现在FROM子句中

selecte.ename,e.sal,e.deptno from emp e

innerjoin (

selectavg(sal) a ,deptno

from emp

group bydeptno) t

one.deptno = t.deptno

wheree.sal>a

 

selecte.ename,e.sal,e.deptno

from empe ,(select avg(sal) avg_sal , deptno

              from emp

              group by deptno

)t

wheree.deptno = t.deptno

and e.sal>avg_sal

子查询中的字段若是函数或者表达式,那必须给别名

 

//放在select子句中,下面相当于左外连接

--放在select子句中

selecte.ename,e.sal ,

(selectd.dname from dept d

  where e.deptno = d.deptno

)deptno

from emp e

 

二.  分页查询

--分页查询是将查询的数据分段显示出来,这样做的目的可以减少资源占用

--提高响应速度

--分页在不同的数据库中的SQL语句是不一样的(方言)

--ORACLE中的分页是依靠伪列:ROWNUM0实现的,ROWNUM不存在于任何表中,但是任何表都可以

--查询该列,该列的值是随着查询数据的过程中生成的,只要可以查询出一条记录,那么ROWNUM字段的值就是

--该记录的行号,从1开始

--在使用rownum对结果集进行编号的过程中

--不要使用rownnum做>1以上的过滤判断,否则结果集将得不到任何记录

selectrownum , ename,sal , deptno from emp

where rownum <15

//实现查询rownum610之间

select *from (

  select rownum rn,ename,sal,deptno from emp

)

where rn between 6 and 10

        

--由于排序在查询语句中的执行顺序是最低的,所以在分页中若有排序需求时,应该最先排序。

--然后再根据排序的结果进行分页查询

select *

from (select rownum rn,t.* from (select ename,sal from emp order bysal desc) t)

where rn between 6 and 10

order by在查询语句中优先级是最低的

//这种方法实现了先里层缩小范围,然后外层再获取的方法,优化了操作

select *

from (select rownum rn,t.* from (selectename,sal from emp order by sal desc) t

where rownum<=10)

where rn >=6

 

//下面公式在java后期掉数据库时候会用到

--根据页数以及每页显示的条目数来求范围的公式

--pageSize:5  每页显示条目数

--page:1      页数

--start = (page-1)*pageSize+1

--end = pageSize*page

 

三.  DECODE函数

--DECODE函数可以实现分支效果

selectename,job,sal,

  DECODE(

    job,

    ‘MANAGER‘,sal*1.2,

    ‘ANALYST‘,sal*1.1,

    ‘SALESMAN‘,sal*1.05,

    sal

  )BONUS

from emp、

上面的方法就是实现三个职位的加工资,如果第四行不加sal的话,除了这三个职位的工资都是null

 

//CASE语句

selectename,job,sal,

  case job when ‘MANAGER‘ then sal*1.2

           when ‘ANALYST‘ then sal*1.1

           when ‘SALESMAN‘ then sal*1.05

           else sal end

           bonus

from emp

//小技巧,可以两个字段放一起统计

可以利用DECODE将字段值不一样的记录看做同一组,只需要将看做一组的记录该字段值替换为一个相同值即可

selectcount(*),

   DECODE (

    job,

    ‘MANAGER‘,‘VIP‘,

    ‘ANALYST‘,‘VIP‘,

    ‘OTHER‘

  )

from emp

groupby  DECODE (

    job,

    ‘MANAGER‘,‘VIP‘,

    ‘ANALYST‘,‘VIP‘,

    ‘OTHER‘

  )

//order by 按照指定decode顺序排列

         selectdeptno , dname,loc

from dept

order by DECODE(

dname,‘OPERATIONS‘,1,‘ACCOUNTING‘,2,‘SALES‘,3

)

 

四.  排序函数

--排序函数允许对结果集按照给定的字段分组,然后再组内按照指定的字段排序,然后生成一个组内编号

--ROW_NUMBER生成组内连续切唯一的数字

selectename,row_number() over(

  partition by deptno

  order by sal

)rank

from emp

 

--RANK:生成组内不连续且不唯一的数字

selectename,sal,deptno,RANK() over(

  partition by deptno

  order by sal desc

)rank

from emp

         --DENSE_RANK:生成组内连续但不唯一的数字(不跳号)

select ename , dense_rank() over(

                  partition by deptno

                 order by sal desc

)

from emp

 

五.  集合操作

//UNION&&UNION ALL

把job是经理并且工资大于2500的两个集合合并,去掉重复

UNION ALL是不去重复

selectename,sal,job from emp where job = ‘MANAGER‘

UNION

selectename,sal,job from emp where sal > 2500

selectename,sal,job from emp where job = ‘MANAGER‘

UNION ALL

select ename,sal,job from emp wheresal > 2500

         //INTERSECT

         取交集

         selectename,sal,job from emp where job = ‘MANAGER‘

intersect

selectename,sal,job from emp where sal > 2500

         //MINUS 上面集合有但是下面集合没有的数据

selectename,sal,job from emp where job = ‘MANAGER‘

MINUS

selectename,sal,job from emp where sal > 2500

 

六.  高级分组函数

//ROLLUP

selectyear_id,month_id,day_id,sum(sales_value)

fromsales_tab

group byrollup(year_id,month_id,day_id)

order by year_id,month_id,day_id

//CUBE全方位统计,三个参数的所有情况都会取到,取到的结果集为2的参数次方

         selectyear_id,month_id,day_id,sum(sales_value)

from sales_tab

group byCUBE(year_id,month_id,day_id)

order byyear_id,month_id,day_id

//GROUPING SETS()

每个参数是一种分组方式,然后将这些分组统计的结果并在一个结果集显示,由于分组方式可以通过参数传入,所以相比ROLLUP 和 CUBE 内定分组相对灵活

select year_id,month_id,day_id,sum(sales_value)

from sales_tab

group byGROUPING SETS((year_id,month_id),(year_id,month_id,day_id),year_id)

order byyear_id,month_id,day_id

视图、序列、索引

一.  视图(在数据库中并不是真实存在)

VIEW也称为虚表,是一组数据的逻辑表示

SELECT搜索出来的数据就是视图

DCL语句:数据控制语言

数据库总创建表的名字不能和数据库对象重复,表的名字最常用

--视图是数据库对象之一

--视图在SQL语句中体现的角色与表一致

--但其并不是表,它只是对应了一个查询语句的结果集

         CREATEVIEW v_emp_10

AS

SELECTempno,ename,sal,deptno

FROM emp

WHERE deptno=10

 

SELECT * FROMv_emp_10

v_emp_10相当于上面的子查询

 

DESC v_emp_10

--视图对应的子查询若含有函数或者表达式,那么必须给个别名,当一个字段使用了别名,那么视图中该字段的名字就是这个别名

         --修改视图

--由于视图只是对应了一个查询语句,所以修改视图就是替换该SQL语句

CREATE ORPEPLACE VIEW v_emp_10

AS

SELECT empno id, ename name,sal salary,deptno

FROM emp

 

//对视图进行DML操作

//对视图进行DML操作就是对视图数据来源的基础表进行的操作。并且只能对视图可见的字段

INSERT INTOv_emp_10 (id,name,salary,deptno)

VALUES(1001,‘JACK‘,5000,10)

UPDATE v_emp_10SET salary=6000

WHERE id=1001

SELECT * FROMemp

SELECT * FROMv_emp_10

//删除表

DELETE FROMv_emp_10

WHERE id=1001

唯一不会对基表造成污染的只有删除操作,插入和更新都会污染表

//通过对视图操作的数据,若视图不可见,那么就等同于对及表数据进行了污染

INSERT INTOv_emp_10 (id,name,salary,deptno)

VALUES(1001,‘JACK‘,5000,20)

UPDATE v_emp_10SET deptno=20

 

//CHECK  OPTION

--为视图添加检查选项可以避免对视图进行DML操作后对基表有数据污染的情况,检查选项要求对视图进行

--DML操作的数据视图必须对其可见,否则不允许操作

CREATE ORREPLACE VIEW v_emp_10

AS

SELECT empno asid , ename as name,sal as salary,deptno

FROM emp

WHERE deptno=10

WITH CHECK OPTION

 

视图一般只会用作重用或者查询

 

//READ ONLY 选项

//当视图添加了只读选项后,该视图仅能查看不能执行任何DML操作

CREATE ORREPLACE VIEW v_emp_10

AS

SELECT empno asid , ename as name,sal as salary,deptno

FROM emp

WHERE deptno=10

WITH READ ONLY

//下面的语法查看了曾经创建的数据库对象,视图和表

SELECTobject_name FROM user_objects

WHEREobject_type=‘TABLE‘

 

SELECT text FROMuser_views

WHERE view_name= ‘V_EMP_10‘

 

SELECT table_nameFROM user_tables

WHERE table_name= ‘EMP‘

 

//复杂视图

不在聚合函数里的字段都需要出现在GROUPBY中,复杂视图出现函数或者表达式都需要加别名

--创建一个各部门工资情况的视图,然后找出员工的工资高于部门平均工资的员工

CREATE VIEWv_emp_dept_salinfo

AS

SELECT  MAX(e.sal) max_sal,

        MIN(e.sal) min_sal,

        AVG(e.sal) avg_sal,

        SUM(e.sal) sum_sal,

        d.deptno,d.dname

FROM emp e ,dept d

WHERE e.deptno = d.deptno

GROUP BY d.deptno,d.dname

 

SELECT e.ename,e.sal,e.eptno

FROM emp e,v_emp_dept_salinfo v

WHERE e.deptno=v.deptno

AND e.sal>v.avg_sal

//删除视图

//删除视图中的数据时,会对应的将基表数据删除,但是删除视图本身时,是不会影响表任何数据的

DROP VIEWv_emp_dept_salinfo

 

二.  序列

CACHE默认20个缓存

--数据库对象之一

--序列是用来生成一系列数字的

--序列生成的数字常被用作某张表主键

--字段的值

CREATESEQUENCE seq_emp_id

STARTWITH 1

INCREMENTBY 1

//序列提供了两个伪列用于获取当前序列的值

--NEXTVAL:获取序列下一个数,这个伪列会导致序列发生步进,序列是不能会退的,即:

--生成下一个数字后,就不能得到之前的数字了

--CURRVAL:获取序列当前值(最后一次生成的值)

--无论调用多少次,都不会导致序列发生步进

--新创建的序列要至少调用一次NEXTVAL后才可以使用CURRVAL

SELECTseq_emp_id.NEXTVAL

FROM dual

SELECTseq_emp_id.CURRVAL

FROM dual

INSERTINTO emp

(empno,ename,sal,job,deptno)

VALUES(seq_emp_id.NEXTVAL,‘ROSE‘,5000,‘CLERK‘,10)

SELECT * FROM emp

        

           缓存更新到数据字典上,每次缓存20个,缓存在内存中,如果断电的话,如果只用到5,那么6到20就断裂了,要从21开始。

           两张表用同一个序列也会出现断裂,两张表同时进行步进

                   //删除序列

DROP SEQUENCE seq_emp_id

          

三.  索引

为了提高查询效率

--索引,数据库对象之一

--作用是提高查询效率

--所以的建立是数据库执行完成的,过程对我们是透明的,我们只需要告诉数据库是否添加索引即可

--索引的应用也是自动的,无需再查询的过程中高告知数据库是否使用索引,数据库会自行判断可用索引

--并自动使用

CREATEINDEX idx_emp_ename

ONemp(ename)

 

--当使用ename作为过滤条件(除like外),作为排序的字段,去重等操作时,数据库会自动

--使用索引idx_emp_ename提高查询效率

         //复合索引

CREATE INDEX idx_emo_job_sal

ONemp(job,sal)

SELECTempno,ename,sal,job FROM emp

ORDER BYjob,sal

//对函数创建索引

CREATEINDEX emp_ename_upper_idx

ONemp(UPPER(ename))

SELECT *FROM emp

WHERE UPPER(ename) = ‘KING‘

 

         //修改和删除索引

//创建ename的索引

CREATE INDEXidx_emp_ename

ON emp(ename)

//修改ename的索引

ALTER INDEXidx_emp_ename REBUILD

//删除ename的索引

DROP INDEXidx_emp_ename

 

//合理使用索引

1.      经常出现在where子句中的列

2.      为经常出现在ORDER BY、DISTINCT后面

3.      为经常作为表的连接条件的列上

4.      不要在经常做DML操作表上建立索引

5.      不要在小表上建立索引

6.      限制表上的索引数目,不是越多越好

7.      删除很少被使用,不合理索引

 

四.  约束

//非空约束

CREATETABLE employees(

  eod number(6),

  nameVARCHAR2(30) NOT NULL,

  salary NUMBER(7,2),

  hiredate DATE CONSTRAINTemployees_hiredate_nn not null

)

--约束分为表级约束与列级约束

--NOTNULL 只是列级约束

--其他约束既是表级也是列级

--列级约束:为某个字段添加约束只能在操作该列的同时进行

--表级约束:可以直接对表进行添加约束

--并指定为该表的那个字段添加

--简单说,添加约束时语法不一样

//设置后期字段非空

ALTERTABLE employees

MODIFY(eodnumber(6) NOT NULL)

//取消非空字段

ALTERTABLE employees

MODIFY (eod number(6) NULL)

         //唯一性约束

         //唯一性约束可以要求某个字段子啊表中任何集中的值不能相同,NULL除外

         CREATETABLE employees1(

                eid NUMBER(6) UNIQUE,

                name VARCHAR2(30),

                email VARCHAR2(50),

                salary NUMBER(7,2),

                hiredate DATE,

                CONSTRAINT employees_email_ukUNIQUE(email)

)

DESC employees1

 

INSERT INTO employees1 (eid,name,email)

VALUES(1,‘jack‘,‘jack@qq.com‘)\

INSERT INTO employees1 (eid,name,email)

VALUES(2,‘jack‘,‘jack1@qq.com‘)

INSERT INTO employees1 (eid,name,email)

VALUES(NULL,‘jack‘,NULL)

SELECT * FROM employees1

                  

         //添加唯一性约束

         ALTERTABLE employees1

ADD CONSTRAINTemployees_name1_uk UNIQUE(name)

如果表中有数据了的话,如果数据有重复数据的话,就不能添加唯一性约束

 

//主键约束

PRIMARY  KEY

主键约束只能建立在单列上,并且一张表只能有一个主键约束,主键约束可以保证字段非空且唯一。

 

//外键约束

正常工作当中很少会使用外检

 

//检查约束

ALTER TABLEemployees2

ADD CONSTRAINTemployees2_salary_check

CHECK (salarybetween 2000 and 5000 )

INSERT INTOemployees2 (eid,salary)

VALUES (10,2500)

 



Oracle基本语法&&函数&&子查询&&分页查询&&排序&&集合操作&&高级分组函数