Oracle

列别名:
当SELECT子句中一个字段是函数或者表达式,那么在结果集中该字段的名字就是这个函数或表达式,可读性差,为此可以为列提供一个别名,这样在结果集中会使用该别名作为该字段的名字。应当养成一个好习惯,即:凡是表达式或函数都指定一个别名。

别名本身不区分大小写,若希望别名区分大小写或者别名中包含空格,那么需要使用双引号将其括起来。
SELECT ename,sal+NVL(comm,0) "sal"FROM emp


OR,AND用于连接多个条件使用:
OR的优先级低于AND,所以若希望提高OR的优先级,可以使用括号。查看工资高于1000,并且职位是CLERK或者SALESMAN的员工?

SELECT  
    ename,job,sal
FROM 
    emp
WHERE 
    sal>1000
AND 
    (job='SALESMAN' OR job='CLERK')

LIKE用于模糊匹配字符串支持两个通配符:
       %:0-多个字符(任意个字符)
        _:单一的一个字符

查看名字第二个字母是A的员工?

SELECT 
    ename,sal,deptno
FROM
    emp
WHERE 
    ename LIKE '_A%'

IN(list) 和 NOT IN(listr)判断在列表中和不在列表中
IN,NOT IN常被用在子查询上使用。

查看职位是CLERK和SALESMAN的员工?

SELECT 
    ename,job,sal
FROM 
    emp
WHERE 
    job IN('CLERK','SALESMAN')

BETWEEN...AND...判断在一个区间范围内:

查看工资在1500到3000之间的员工?

SELECT 
    ename,sal
FROM 
    emp
WHERE 
    sal BETWEEN 1500 AND 3000

查看工资在1000-3000之间,20和30号部门名字中含有A的员工?

SELECT 
    ename,sal,deptno,job
FROM 
    emp
WHERE 
    sal BETWEEN 1000 AND 3000 AND deptno IN (20,30) AND ename LIKE '%A%'


ANY(list),ALL(list):
ANY,ALL是配合>,>=,<,<=使用的
>ANY(list):大于列表之一,大于最小
>ALL(list):大于列表所有,大于最大
ANY,ALL的列表中不会给定固定值,没有
实际意义,它们通常配合子查询使用。

SELECT 
    empno, ename, job,sal, deptno
FROM 
    emp
WHERE sal>ANY(3500,4000,4500)

DISTINCT关键字:
DISTINCT可以将结果集中指定字段值一样的记录去重。

查看公司有哪些职位?

SELECT DISTINCT job FROM emp

可以按照多字段去重,那么这些字段值的组合没有重复记录出现在结果集中。

SELECT DISTINCT deptno,job FROM emp

ORDER BY子句:
ORDER BY用于对查询的结果集按照指定
字段的值进行排序。
排序分为:升序(ASC),降序(DESC).
默认为升序
ORDER BY子句必须定义在SELECT语句中
的最后一个子句上。

查看公司中工资的排名?

SELECT 
    ename,sal,job
FROM 
    emp
ORDER BY 
    sal DESC

查看20号部门的工资排名?

SELECT 
    ename,sal,deptno
FROM 
    emp
WHERE 
    deptno=20
ORDER BY 
    sal DESC

多字段排序时,ORDER BY是有排序的优先级的,首先按照第一个字段先进行排序,当该字段中有记录值重复时,再将这些记录按照第二个字段排序。依此类推。

SELECT 
    ename,deptno,sal
FROM 
    emp
ORDER BY 
    deptno DESC,sal DESC

若排序的字段中含有NULL值,NULL被认定为最大值。

SELECT ename,comm FROM emp ORDER BY comm


聚合函数:
聚合函数又称为分组函数,多行函数。聚合函数的作用是对结果集指定字段的值进行统计工作的。MAX(),MIN(),SUM(),AVG()求最大值,最小值,总和,平均值,还有一个是对记录数的统计COUNT()。


查看公司的最高工资是多少?

SELECT MAX(sal) FROM emp

SELECT MAX(sal),MIN(sal),SUM(sal),AVG(sal) FROM emp

查看公司共多少人?

SELECT COUNT(ename) FROM emp
SELECT COUNT(*) FROM emp
SELECT COUNT(1) FROM emp

聚合函数忽略NULL值。

SELECT SUM(comm),AVG(comm)FROM emp

SELECT AVG(NVL(comm,0)) FROM emp

分组:
GROUP BY子句
GROUP BY子句可以将结果集按照给定的字段值一样的记录进行分组。配合聚合函数使用可以完成分组统计工作。

查看每个部门的平均工资?

SELECT 
    AVG(sal),deptno
FROM 
    emp
GROUP BY deptno

当SELECT中含有聚合函数时,那么凡不在聚合函数中的单独字段,都需要出现在GROUP BY子句中。

查看每种职位的最高工资与最低工资是多少?

SELECT 
    MAX(sal),MIN(sal),job
FROM 
    emp
GROUP BY job

GROUP BY按照多字段分组时,是将这些字段值组合一样的记录看做一组。


统计同部门同职位的员工的各多少人?

SELECT 
    COUNT(*),deptno,job
FROM 
    emp
GROUP BY deptno,job

查看部门的平均工资,前提是该部门的平均工资高于2000

SELECT 
    AVG(sal),deptno
FROM 
    emp
WHERE 
    AVG(sal)>2000
GROUP BY deptno

上面的SQL语句会抛出异常,WHERE子句中是不能使用聚合函数做为过滤条件的,原因在于过滤的时机不对。WHERE是伴随查询表中数据逐行进行过滤使用的,用来确定结果集中可以查询出的条目数。而聚合函数是建立在查询出来的数据基础上进行统才能得到结果,所以使用聚合函数过滤应当是在WHERE之后进行的。HAVING子句可以根据聚合函数进行过滤,并且是用来根据条件过滤 GROUP BY的分组。HAVING不能单独出现,不定义GROUP BY子句不能单独出现HAVING子句。

查看部门的平均工资,前提是该部门的平均工资高于2000

SELECT 
    AVG(sal),deptno
FROM 
    emp
GROUP BY 
    deptno
HAVING 
    AVG(sal)>2000

查看平均工资高于2000的那些部门的最高工资是多少?

SELECT 
    MAX(sal),deptno
FROM 
    emp
GROUP BY 
    deptno
HAVING 
    AVG(sal)>2000

关联查询
关联查询的结果集中的字段来自多张表。这就需要在查询的时候联合多张表进行查询,根据给定的连接条件将表与表的数据建立对应关系,再分别从这些记录中提取要查询的字段来形成结果集中的每条记录。

查看每个员工的名字以及其所在部门的名字?

SELECT 
    ename,dname
FROM 
    emp,dept
WHERE 
    emp.deptno=dept.deptno

当在关联查询中要查询的字段在这些表中都出现时,需要使用表名来明确字段所属表。可以为表名取一个别名来简化复杂度。

SELECT 
    e.ename,e.deptno,d.dname
FROM 
    emp e,dept d
WHERE 
    e.deptno=d.deptno

在进行关联查询时若有过滤要求,那么过滤条件必须与连接条件同时成立。


查看在NEW YORK工作的员工都有谁?

SELECT 
    e.ename,e.deptno,d.dname,d.loc
FROM 
    emp e,dept d
WHERE 
    e.deptno=d.deptno AND d.loc='NEW YORK'

关联查询中不指定连接条件或者连接条件无效时,会产生笛卡尔积,这通常是一个无意义的结果集。

SELECT e.ename,d.dname FROM emp e, dept d

N表查询至少要有N-1个连接条件。


内连接
内连接也是用来完成关联查询的。采用JOIN...ON...的形式关联多表。

查看每个员工的名字以及其所在部门名称?

SELECT e.ename,d.dname FROM emp e,dept d WHERE e.deptno=d.deptno

内连接写法:

SELECT 
    e.ename,d.dname
FROM 
    emp e 
JOIN 
    dept d
ON 
    e.deptno = d.deptno

不满足关联条件的记录不会被查询出来。

外链接
外链接在关联查询中除了可以将满足连接条件的记录查询出来之外,还可以将不满足连接条件的记录也列出来。
外链接分为:
左外连接,右外连接,全外连接
左外连接:以JOIN左侧表做为驱动表,该表记录都要查询出来,当某条记录不满足连接条件时,那么在结果集中该条记录来自JOIN右侧表的字段的值全部为NULL。

SELECT 
    e.ename,e.job,e.sal,d.dname,d.loc
FROM 
    emp e 
LEFT|RIGHT|FULL OUTER JOIN 
    dept d
ON 
    e.deptno=d.deptno
SELECT 
    e.ename,d.dname
FROM 
    emp e,dept d
WHERE 
    e.deptno(+)=d.deptno

自连接
自连接指的是当前表的一条数据可以对应当前表自己的多条数据。
自连接是为了解决数据的属性相同,但是本身又存在上下级关系的树状结构数据。查看每个员工以及其领导的名字?

SELECT 
    e.ename,m.ename
FROM 
    emp e,emp m
WHERE 
    e.mgr=m.empno(+)

SELECT 
    e.ename,m.ename
FROM 
    emp e 
LEFT OUTER JOIN 
    emp m
ON 
    e.mgr=m.empno

子查询
子查询是一条查询语句,它是嵌套在其他SQL语句中的,目的是将查询的结果提供给外层的SQL语句。

查看谁的工资高于CLARK的工资?

SELECT 
    ename,sal FROM emp
WHERE 
    sal>(SELECT sal FROM emp WHERE ename='CLARK')

查看与CLARK同部门的员工?

SELECT 
    ename,deptno
FROM 
    emp
WHERE 
    deptno=(SELECT deptno FROM emp WHERE ename='CLARK')
AND 
    ename<>'CLARK'  

查看高于公司平均工资的员工?  

SELECT 
    ename,sal
FROM 
    emp
WHERE 
    sal>(SELECT AVG(sal) FROM emp)  

在DDL中使用子查询,可以将一个子查询的结果集当做表快速创建出来。

CREATE TABLE 
    employee
AS
    SELECT e.empno,e.ename,e.sal,e.job,d.deptno,d.dname,d.loc
FROM 
    emp e,dept d
WHERE 
    e.deptno=d.deptno(+)

在使用子查询创建表的时候,查询多少个字段创建的表就有多少个字段,字段名与查询的字段名字一致(不含有表别名),类型,长度也一致。但是需要注意的是,若查询的字段是函数或者表达式,那么这个字段必须指定别名,并且生成的表对应的该字段名就是这个别名。
DML中使用子查询


将CLARK所在部门的员工工资上浮10%

UPDATE 
    emp
SET 
    sal=sal*1.1
WHERE 
    deptno=(SELECT deptno FROM emp WHERE ename='CLARK')

子查询根据查询结果分为:
单行单列,多行单列,多行多列子查询其中单列子查询常用在过滤条件中多列子查询常被当做表使用。

对于多行单列子查询在进行过滤判断时,需要配合IN,ANY,ALL使用。

查看与职位是SALESMAN同部门的员工?

SELECT 
    ename,job,deptno
FROM 
    emp
WHERE 
    deptno IN (SELECT deptno FROM emp WHERE job='SALESMAN')
AND 
    job<>'SALESMAN'

查看比职位是SALESMAN和CLERK工资都高的员工?

SELECT 
    ename,sal,job
FROM 
    emp
WHERE 
    sal>ALL(SELECT sal FROM emp WHERE job IN('SALESMAN','CLERK'))

SELECT deptno, dname FROM dept d

EXISTS关键字
EXISTS用在WHERE中进行过滤,其后跟一个子查询,只要该子查询至少可以查询出一条记录,那么则该条件为true.

查看有下属的员工?

SELECT 
    m.ename,m.job,m.sal
FROM 
    emp m
WHERE 
    EXISTS(SELECT * FROM emp e WHERE e.mgr = m.empno)

HAVING中使用子查询:
查看每个部门的最低薪水,前提是要高于30号部门的最低薪水?

SELECT 
    MIN(sal),deptno FROM emp
GROUP BY 
    deptno
HAVING 
    MIN(sal)>(SELECT MIN(sal) FROM emp WHERE deptno=30)

在FROM中使用子查询通常多列子查询在FROM子句中出现,作用是当做一张表使用。

查看高于自己所在部门平均工资的员工?

SELECT 
    e.ename,e.sal,e.deptno
FROM 
    emp e,(SELECT deptno,AVG(sal) avg_sal FROM emp GROUP BY deptno) x
WHERE 
    e.deptno=x.deptno AND e.sal>x.avg_sal

分页查询:
分页查询就是将表中要查询出来的数据分批分段查询出来。这样做的好处是当查询的数据量过大时可以减少内存开销,
提高系统响应速度,减少网络传输。分页是方言,不同数据库都提供了分页查询的机制,但是语法定义各不相同。

ORACLE是依靠提供了一个伪列:ROWNUMROWNUM不存在于任何一张表中,但是每张表都可以查询该字段,该字段在结果集中的值就是每条记录的行号。而行号的生成是伴随查询过程进行的,只要可以从表中查询出一条记录,ROWNUM字段就是为该条记录在结果集中产生对应的行号,从1开始递增。

需要注意,在使用ROWNUM对结果集编行号的过程中,不要使用ROWNUM做大于1以上数字的判断,否则得不到结果。

SELECT 
    ROWNUM,ename,job,sal
FROM 
    emp
WHERE 
    ROWNUM >1
SELECT 
    *
FROM
    (SELECT ROWNUM rn,ename,job,sal FROM emp)
WHERE 
    rn BETWEEN 6 AND 10

查看公司工资排名的第6-10名

SELECT 
    *
FROM
    (SELECT ROWNUM rn,t.* FROM(SELECT ename,job,sal FROM emp ORDER BY sal DESC) t)
WHERE 
    rn BETWEEN 6 AND 10
SELECT 
    *
FROM
    (SELECT ROWNUM rn,t.* FROM(SELECT ename,job,sal FROM emp ORDER BY sal DESC) t WHERE ROWNUM <=10 )
WHERE 
    rn >= 6

换算范围的公式:
PageSize:每页可以显示的条目数
Page:页数

start:(Page-1)*PageSize + 1
end:PageSize*Page


DECODE函数
DECODE函数可以实现分支结构

SELECT
    ename, job, sal,DECODE(job,'MANAGER', sal * 1.2,'ANALYST', sal * 1.1,'SALESMAN', sal * 1.05,sal) bonus
FROM 
    emp;


DECODE在GROUP BY中可以实现将字段不同值的记录分为一组。
将职位是ANALYST与MANAGER看做一组,其他职位看做另一组,分别统计人数?

SELECT 
     COUNT(*),DECODE(job,'MANAGER','VIP','ANALYST','VIP','OTHER') 
FROM 
    emp
GROUP BY 
    DECODE(job,'MANAGER','VIP','ANALYST','VIP','OTHER') 


排序函数
排序函数可以将结果集按照指定的字段分组然后组内再按照指定的字段排序后对每组的记录产生一个行号。

ROW_NUMBER():生成组内连续且唯一的数字。

查看每个部门的工资排名?

SELECT 
 ename,job,sal,deptno,ROW_NUMBER() OVER(PARTITION BY deptno ORDER BY sal DESC) rank
FROM
    emp

RANK():生成组内不连续也不唯一的数字

SELECT 
    ename,job,sal,deptno,RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) rank
FROM  
    emp

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

SELECT 
    ename,job,sal,deptno,DENSE_RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) rank
FROM 
    emp

高级分组函数

查看每天的营业额?

SELECT 
    year_id,month_id,day_id,SUM(sales_value)
FROM 
    sales_tab
GROUP BY 
    year_id,month_id,day_id
ORDER BY 
    year_id,month_id,day_id

查看每月的营业额?

SELECT 
    year_id,month_id,SUM(sales_value)
FROM 
    sales_tab
GROUP BY 
    year_id,month_id
ORDER BY 
    year_id,month_id

查看每年的营业额?

SELECT 
    year_id,SUM(sales_value)
FROM 
    sales_tab
GROUP BY 
    year_id
ORDER BY 
    year_id

查看总共的营业额?

SELECT SUM(sales_value) FROM sales_tab

在一个结果集中看到每天,每月,每年以及总共的营业额?

SELECT 
    year_id,month_id,day_id,SUM(sales_value) 
FROM 
    sales_tab
GROUP BY 
    year_id,month_id,day_id
UNION 
    ALL

SELECT 
    year_id,month_id,NULL,SUM(sales_value)
FROM 
    sales_tab
GROUP 
    BY year_id,month_id
UNION 
    ALL

SELECT 
    year_id,NULL,NULL,SUM(sales_value)
FROM 
    sales_tab
GROUP BY 
    year_id
UNION 
    ALL

SELECT NULL,NULL,NULL,SUM(sales_value) FROM sales_tab


ROLLUP()函数
ROLLUP中的每一个参数就是需要分组的字段。
ROLLUP会将参数字段逐个递减并分组统计直至一个字段都没有,然后将这些分组统计的结果并在一个结果集显示

GROUP BY ROLLUP(a,b,c)
等价:
GROUP BY a,b,c
UNION ALL 
GROUP BY a,b
UNION ALL 
GROUP BY a
UNION ALL
全表

在一个结果集中看到每天,每月,每年以及总共的营业额?

SELECT 
    year_id,month_id,day_id,SUM(sales_value) 
FROM 
    sales_tab
GROUP BY 
    ROLLUP(year_id,month_id,day_id)
ORDER BY 
    year_id,month_id,day_id

CUBE()函数,将每个参数的每种组合都进行一次分组,然后将所有统计的结果并在一个结果集显示,所以CUBE分组次数为2的参数个数次方。
GROUP BY CUBE(a,b,c)
abc
ab
bc
ac
a
b
c
全表

SELECT 
    year_id,month_id,day_id,SUM(sales_value)
FROM 
    sales_tab
GROUP BY 
    CUBE(year_id,month_id,day_id)
ORDER BY 
    year_id,month_id,day_id

GROUPING SETS()
GROUPING SETS的每一个参数是一种分组方式它会将这些分组统计的结果并在一个结果集显示。查看每天与每月营业额?

SELECT 
    year_id,month_id,day_id,SUM(sales_value)
FROM 
    sales_tab
GROUP BY 
    GROUPING SETS((year_id,month_id,day_id),(year_id,month_id))
ORDER BY 
    year_id,month_id,day_id

GROUP BY year_id,month_id,day_id
GROUP BY year_id,month_id

视图VIEW
视图是数据库对象之一,在SQL语句中体现的角色与表一致。但是视图并非一张真实存在的表,它只是一个查询语句对应的结果集。

CREATE 
    VIEW v_emp_10
AS
    SELECT empno, ename, sal, deptno FROM emp 
WHERE 
    deptno = 10

DESC v_emp_10

SELECT * FROM v_emp_10

视图对应的子查询中的字段可以指定别名,这样该视图对应的字段名就是这个别名。当一个字段是函数或者表达式,那么该字段
必须指定别名

CREATE 
    OR REPLACE VIEW v_emp_10 
AS
    SELECT empno id,ename name,sal salary,deptno
FROM 
    emp
WHERE 
    deptno=10

视图根据对应的子查询不同,分为简单视图和复杂视图
简单视图:对应的子查询不含有函数,表达式,分组,去重,关联查询。
除了简单视图就是复杂视图

简单视图可以进行DML操作,对该视图的操作就是对该视图数据来源的基础表进行的操作。
复杂视图不允许进行DML操作。
对简单视图进行DML操作也不能违反基础表的约束条件。
对视图进行DML操作,视图对基础表操作时,只能对视图可见的字段进行。

INSERT INTO 
    v_emp_10(id,name,salary,deptno)
VALUES
    (1001,'JACK',3000,10)

SELECT * FROM v_emp_10
SELECT * FROM emp

UPDATE v_emp_10 SET salary=4000 WHERE id=1001

DELETE FROM v_emp_10 WHERE id=1001

对视图的不当DML操作会污染基表数据 即:对视图进行DML操作后,视图对基础表
对应数据进行该DML操作,但是操作后视图却对该记录不可见。

INSERT INTO v_emp_10(id,name,salary,deptno) VALUES(1001,'JACK',3000,20)
UPDATE v_emp_10 SET deptno=20

DELETE不会产生污染现象。
DELETE FROM v_emp_10 WHERE deptno=20

为视图添加检查选项,可以避免对视图操作而导致的对基表的数据污染。
WITH CHECK OPTION
该选项要求对视图进行DML操作后,该记录必须对视图可见。

CREATE OR REPLACE VIEW 
    v_emp_10
AS
    SELECT empno id,ename name,sal salary,deptno
FROM 
    emp
WHERE 
    deptno=10
WITH CHECK OPTION

只读选项
WITH READ ONLY
只读选项要求对视图仅能进行查询操作不能进行任何DML操作。

CREATE OR REPLACE VIEW 
    v_emp_10
AS
    SELECT empno id,ename name,sal salary,deptno
FROM 
    emp
WHERE 
    deptno=10 
WITH READ ONLY

常用的数据库的数据字典
USER_OBJECTS:记录用户创建过的所有数据库对象

SELECT 
    object_name,object_type 
FROM 
    user_objects
WHERE 
    object_type='VIEW' AND object_name LIKE '%FANCQ'

USER_VIEWS:专门记录曾经创建过的视图信息

SELECT view_name,text FROM user_views

USER_TABLES:专门记录曾经创建过的表的信息

SELECT table_name FROM user_tables

删除视图
DROP VIEW v_emp_10

创建复杂视图
创建一张视图,包含员工工资及相关部门信息包含:每个部门的平均工资,最大,最小,工资总和,以及对应的部门名称,部门编号。

CREATE OR REPLACE VIEW 
    v_emp_salinfo
AS
    SELECT AVG(e.sal) avg_sal,MAX(e.sal) max_sal,MIN(e.sal) min_sal,SUM(e.sal) sum_sal,d.deptno,d.dname,d.loc
FROM 
    emp e,dept d
WHERE 
    e.deptno=d.deptno
GROUP BY 
    d.deptno,d.dname,d.loc

查看哪些员工的工资高于其所在部门平均工资?

SELECT 
    e.ename,e.sal,e.deptno
FROM 
    emp e,v_emp_salinfo v
WHERE 
    e.deptno=v.deptno AND e.sal>v.avg_sal

SELECT * FROM v_emp_salinfo

序列SEQUENCE
序列是数据库对象之一,作用是根据指定的规则生成一系列数字。通常使用序列生成的数字是为表中的主键字段提供值使用。

CREATE SEQUENCE seq_emp_id START WITH 1 INCREMENT BY 1

序列支持两个伪列:
NEXTVAL:获取序列的下一个数字,如果是新创建的序列,那么会从START WITH开始返回。之后则是用上次生成的数字加上步长来得到本次生成的数字返回。需要注意,序列是不能后退的。并且不受事务控制。

CURRVAL:获取序列最后生成的数字,新创建的序列至少调用NEXTVAL生成一个数字后才可以使用。CURRVAL不会导致序列步进。

SELECT seq_emp_id.NEXTVAL FROM dual
SELECT seq_emp_id.CURRVAL FROM dual

使用序列为EMP表主键字段提供值:

INSERT INTO emp(empno,ename,job,sal,deptno) VALUES(seq_emp_id.NEXTVAL,'JACK','CLERK',3000,10)

SELECT * FROM emp

删除一个序列

DROP SEQUENCE seq_emp_id

序列的数据字典

SELECT * FROM USER_SEQUENCES

索引INDEX
索引是数据库对象之一,作用是提高查询效率索引的创建时是数据库自行完成的,并且数据库会在适当的时候自动使用索引。

CREATE INDEX idx_emp_ename ON emp(ename)

经常出现在WHERE中和ORDER BY中的字段要添加索引。经常出现在DISTINCT后面的字段也可以添加索引。
需要注意,对于字符串类型字段,若在WHERE中使用LIKE进行过滤时,是不会用到索引的。
约束

唯一性约束

CREATE TABLE 
    employees2 (eid NUMBER(6) UNIQUE,name VARCHAR2(30),email VARCHAR2(50),salary NUMBER(7, 2),hiredate DATE,CONSTRAINT employees_email_uk UNIQUE(email))
INSERT INTO 
    employees2(eid,name,email)
VALUES(NULL,'jack',NULL)

SELECT * FROM employees2


主键约束
一张表只能有一个字段定义主键约束,主键约束要求该字段非空且唯一

CREATE TABLE employees3 (
  eid NUMBER(6) PRIMARY KEY,
  name VARCHAR2(30),
  email VARCHAR2(50),
  salary NUMBER(7, 2),
  hiredate DATE
)
INSERT INTO employees3
(eid,name,email)
VALUES
(2,'jack','[email protected]')

 

你可能感兴趣的:(Oracle)