Oracle重点知识点总结

1,万能表dual,由oracle自己维护

2,Oracle多表查询中的重要知识点:

左联接的缩写(下面是右联结)

SELECT * FROM emp t1,dept t2 WHERE t1.deptno(+) =t2.deptno;--有加号的一边是从表,这个表示右外连接!

全外连接(full,左右两边都有空的每一行值都会查出来!)

SELECT * FROM emp t1 FULL OUTER JOIN dept t2 ON t1.deptno =t2.deptno;

自查询(将自己分成两个表,查员工和员工上司)

SELECT * FROM emp t1, emp t2 WHERE t1.mgr=t2.empno;(隐式内链接)

SELECT * FROM emp t1 ,emp t2 WHERE t1.mgr=t2.empno(+);(左联接)

子查询中注意(子查询语句不能为空,只要子语句为空不管怎样 整个语句的结果都为空)

SELECT * FROM emp WHERE job !=(SELECT job FROM emp WHERE ename='Rose');

子查询的位置:可以放在主查询的where、select、having、from的后面。不可以放在主查询的group by后面。

最后,子查询出来的表也可以当作虚拟表来再次查询

条件的使用顺序!(where--> group by -->  having (having必须依赖group by使用)-->  order by)

SELECT deptno,MAX(sal) FROM emp WHERE deptno IS NOT NULL GROUP BY deptno HAVING avg(sal)>2000 ORDER BY deptno DESC;

3,伪列:(根据rownum查询时候,不能rownum>=什么,它是查询的时候自然生成的【故不会随order by而改变顺序】,且从0开始往上加所以不能:rownum>=什么)

例:查询第四到六rownum值时

SELECT *  FROM (SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM<=6) t1 WHERE r>=4;

--分页查询: 每页显示3条,当前第二页

pageNum=2;

pageSize=3;

firstIndex=(pageNum-1)pageSize

maxCount=pageSize;

 

mysql中分页:

SELECT * FROM emp LIMIT firstIndex,maxCount;

SELECT * FROM emp LIMIT 1,2;

oracle中分页:

pageNum=2;

pageSize=3;

StartRownum =(pageNum-1)*pageSize+1;

endRowNum=pageNum*pageSize;

SELECT * FROM  (SELECT ROWNUM r,t.* FROM emp t WHERE ROWNUM<=StartRownum) t1  WHERE t1.r>=endRowNum;

伪列:ROWID的作用

这里列举两个常见的应用:

?I,去除重复数据。(因为它是插入数据时候就有的数据,当两条数据相同时候,他们的唯一标识就有且只有rowid了,所以可以通过以下方法去重复)--面试题—了解

--剔除重复数据

SELECT * FROM TEST WHERE ROWID NOT in(SELECT MIN(ROWID) FROM TEST GROUP BY NAME);

?II,在plsql Developer中,加上rowid可以更改数据。

3,如何避免笛卡儿积

在 WHERE 加入有效的连接条件。

4,如何解决高水位带来的查询效率问题呢?

I.将表数据备份出来,摧毁表再重建(truncate table),然后再将数据导回来。(释放空间)

II.收缩表,整理碎片,可使用变更表的语句:alter table 表名 move(不是放空间)rowid发生了变化。

5,索引:

作用:提升查询效率,提升服务器的i/o性能(减少了查询的次数)!

如果建立索引的时候,没有指定表空间,那么默认索引会存储在哪个表空间.会存储在所属用户默认的表空间

自动创建索引 非唯一,加速查询

生产环境下一般要将索引单独指定表空间(不要设置参数)

create index idx_emp_ename on EMP (ename) tablespace USERS;

索引的创建场景!

l下列情况不要创建索引:

n表很小

n列不经常作为连接条件或出现在WHERE子句中

n表经常频繁更新(看需求,如果表经常不断的再更新,Oracle会频繁的重新改动索引,反  而降低了数据库性能。但如系统日志历史表,就必须增加索引,效率超高)

 

面试题:

1. 索引的作用是什么?

主要是提高查询效率,减少磁盘的读写,从而提高数据库性能。

2. 创建索引一定能提高查询速度么?

未必!得看你创建的索引的合理性。

3. 索引创建的越多越好么?

不是!索引也是需要占用存储空间的,过多的索引不但不会加速查询速度,反而还会降低效率。

 

6,plsql编程

引用型变量: v_ename emp.ename%TYPE;表的某个列

记录型变量: v_emp emp%ROWTYPE;表的一行的每一列( SELECT * INTO v_emp FROM emp WHERE empno=7839;)

流程控制:1,if判断:

判断emp表中记录是否超过20条,,10-20之间,10以下打印一句

--判断emp表中记录是否超过20条,,10-20之间,10以下打印一句

DECLARE

  --用来存储数量

  v_count NUMBER;

BEGIN

  --查询数量赋值

  SELECT COUNT(1) INTO v_count FROM emp ;

  --判断

  IF v_count>20 THEN

    dbms_output.put_line('记录数超过20条:'||v_count);

  ELSIF v_count BETWEEN 10 AND 20 THEN  

  dbms_output.put_line('记录数在10到20条之间:'||v_count);

  ELSE

    dbms_output.put_line('记录数不足10条:'||v_count);

  END IF;  

END;

2,LOOP循环

打印数字1-

--打印数字1-10

DECLARE

  --声明一个变量

  v_num NUMBER :=1;

BEGIN

   --循环并打印

   LOOP

     EXIT WHEN v_num>10; --退出循环条件

     dbms_output.put_line(v_num);

     --递增

     --v_num++;--不支持

     v_num :=v_num+1;

   END LOOP;

END;

7,游标:

从某个表中按照某种条件查出值,作为游标,在操作时候,打开游标 将取出的游标中的值 放进你声明的变量中,加一个退出条件,将它遍历放入!结果:变量可以可以得到我们所注入的一个结果集!

 

使用游标查询并打印某部门的员工的姓名和薪资,部门编号为运行时手动输入。

 

-- Created on 2015/5/5 by CLARK

---查询10号部门的员工的姓名和薪资

declare 

   --定义游标--带参数的游标:需要定一个形式参数

   CURSOR c_emp(v_deptno emp.deptno%TYPE) IS SELECT ename,sal FROM emp WHERE deptno=v_deptno ;

   

   --声明变量

   v_ename emp.ename%TYPE;

   v_sal emp.sal%TYPE;

 

BEGIN

  --用

  --打开游标

  OPEN c_emp(10);

  --循环fetch

  LOOP      

      --取出数据

      FETCH c_emp INTO v_ename,v_sal;

--退出条件

      EXIT WHEN c_emp%NOTFOUND;

      --打印--写任何的逻辑

      dbms_output.put_line('姓名:'||v_ename||',薪资:'||v_sal);   

  END LOOP;

  --关闭

  CLOSE c_emp;

end;

 

 

--使用游标查询并打印某部门的员工的姓名和薪资,部门编号为运行时手动输入。

DECLARE

  --声明一个带参数的游标

  CURSOR C_EMP(v_deptno emp.deptno%TYPE) IS SELECT * FROM EMP WHERE deptno=v_deptno;

  --记录型变量

  v_emp emp%ROWTYPE;

 

BEGIN

  --打开游标,执行查询

  --打开游标的时候需要传入参数

  OPEN C_EMP(20);

  --使用游标,循环取值

  LOOP  

    --获取游标的值放入变量的时候,必须要into前后要对应(数量和类型)

    FETCH C_EMP INTO v_emp;  

    EXIT WHEN C_EMP%NOTFOUND;  

    --输出打印

    DBMS_OUTPUT.PUT_LINE('员工的姓名:' || v_emp.ename || ',员工的工资' || v_emp.sal);  

  END LOOP;

  

  CLOSE c_emp ;--关闭游标,释放资源  

END;

8,存储过程:

作用:

为了一个特定的业务功能,会向数据库进行多次连接关闭(连接和关闭是很耗费资源)

业务放到PLSQL中:应用程序中只需要调用PLSQL就可以做到连接关闭一次数据库就可以实现我们的业务,可以大大提高效率.

 

java是不能直接调用plsql的,但可以通过存储过程这些对象来调用。

 

存储过程的调用方法:

Pl/sql调用:申明输入数据和输出数据类型,以及输入数据的传参

再打印你想要得到的值

Command窗口执行:打开服务 set serveroutput on;然后exec P_hello存储名(参数)(只有输入参数时可以,有输出的时候没有成功,方法此时用上面的)

Java程序调用:没试过!

【示例】

输入员工号查询某个员工(7839号员工)信息,要求,将薪水作为返回值输出,给调用的程序使用。

----输入员工号查询某个员工(7839号(老大)员工)信息,要求,将薪水作为返回值输出,给调用的程序使用。

CREATE OR REPLACE PROCEDURE p_queryempsal_out( i_empno IN emp.empno%TYPE,o_sal OUT emp.sal%TYPE)

AS

BEGIN

  --赋值:将薪水的值赋给输出的参数o_sal

  SELECT sal INTO o_sal FROM emp WHERE empno=i_empno;  

 

END;

 

 

调用(使用plsql程序调用):

 

DECLARE

  --输入参数值

  v_empno emp.empno%TYPE:=7839;

  --声明一个变量来接收输出参数

  v_sal emp.sal%TYPE;

 

BEGIN

 

  p_queryempsal_out(v_empno,v_sal);--第二个参数是输出的参数,必须有变量来接收!!

  --当上面的语句执行之后,v_sal就有值了。

  

  dbms_output.put_line('员工编号为:'||v_empno||'的薪资为:'||v_sal);

END;

/

 

注意:调用的时候,参数要与定义的参数的顺序和类型一致

 

9,触发器:

触发器就是在执行某个操作(增删改)的时候触发一个动作(一段程序)。

触发器分类:

l 语句级触发器(表级触发器)

在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行 。

l 行级触发器(FOR EACH ROW)

触发语句作用的每一条记录都被触发。在行级触发器中使用old和new伪记录变量, 识别值的状态。

语句级触发器和行级触发器区别:

1. 在语法上,行级触发器就多了一句话:for each row

2. 在表现上,行级触发器,在每一行的数据进行操作的时候都会触发。但语句级触发器,对表的一个完整操作才会触发一次。

简单的说:行级触发器,是对应行操作的;语句级触发器,是对应表操作的。

 

但是要注意:触发器会引起锁,降低效率!使用时要慎重。如无必要,尽量不要使用触发器。

行级触发器会引发行级锁(锁行数据)

语句级触发器可能会引起表级锁(锁表)

 

10,Sql优化:

【知识点】

SQL优化:(where条件特别多的情况下,就有效果了)

where条件的解析顺序:从右到左

对于and,应该尽量把假的放到右边。

对于or,应该尽量把真的放到右边。

有where子查询时,子查询放在最前;(where从右向左执行,故右边的条件先执行后再子查询可以缩小查询范围)

213623_YPeP_3033640.png

 

到底是使用upper还是使用lower呢?

一般根据需求来选择的。

如果将函数放到字段上,会每行的该字段都会转换,效率低一些。--sql优化

因此,一般情况下,建议将转换函数放到固定值上面(好处之一就是只需要转换一次,还有一个好处,就是你不知道用户到底输入的是大写还是小写还是混合写,更适应业务)。

 

能用where就用where别用having!!

使用having子句过滤,是先分组,再过滤,注意:分组的时候是全表扫描的,效率较低。

使用where子句过滤,是先过滤再分组,注意:分组的时候仅需要扫描部分数据,效率较高。

 

在查两个表时候,如果有相同字段,咱么要加上表前缀,这样可以提升性能!

即是:select语句中尽量避免使用*(执行时会把*依次转换为列名);

查两张以上表时,把记录少的放在右边;

213607_1L7o_3033640.png

213559_WXjK_3033640.png

213549_rgvW_3033640.png 

 

 

 

 

213533_iay0_3033640.png

用索引提高效率(代价是:索引需要空间,而且定期重构索引很有必要:ALTER INDEX<INDEXNAME> REBUILD<TABLESPACENAME);

 

先介绍下索引的原理,方便接下来对索引的优化的理解:

 

     通过索引找到rowid,然后通过rowid访问表。但如果查询的列包括在index中,将不在执行第二部操作,因为检索数据保存在索引中,单单访问索引就可以完全满足查询要求。

 

前提提要:LODGING列有唯一索引;MANAGER列上有非唯一性索引。

 

索引范围查询(INDEX RANGE SACEN):

        适用于两种情况:

        1)基于一个范围的查询:

              SELECT LODGING FROM LODGING WHERE LODGING LIKE 'M%'

        (where字句条件包括一系列的值,oracle将通过索引范围查询方式查询LODGING_PK)

        2) 基于非唯一性索引的检索:

              SELECT LODGING FROM LODGING WHERE MANAGER = 'LI';

         (此查询分两步:LODGING$MANAGER的索引范围查询得到所有符合条件记录的rowid,然后通过rowid访问表得到LODGING列的值。该索引为非唯一性索引,数据库不能对它执行索引唯一扫描)

where字句中,如果索引列所对应的值的第一个字符由通配符开始,索引将不被采用,而会全表扫描,如 SELECT..... WHERE MANAGER LIKE '%LI'

 

213502_vOEd_3033640.png

转载于:https://my.oschina.net/u/3033640/blog/819539

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值