oracle基础笔记整理
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
select sysdate,systimestamp from dual
create table stud(
stuid varchar2(7)not null,
stuname varchar2(10)not null,
sex varchar2(2)not null,
age number(2)not null,
seat number(2) not null,
enrolldate date,
stuaddress varchar2(50)default'地址不详',
classNO varchar2(4)not null
)
select * from stud;
alter table stud add constraint pk_stud primary key(stuid);--创建一个主键约束、
alter table stud add constraint ck_stud_sex check(sex = '男' or sex ='女');--创建一个性别的检查约束
alter table stud add constraint ck_stud_seat check(seat>=0 and seat <=50 );---创建一个座位号的检查约束
alter table stud add constraint ck_stud_age check(age>=o and age<=100);--创建一个年龄的检查约束
alter table stud add constraint ck_stud_classNo check((classNo>='1001' and classNo<='1999')
or(classNo>='2001'and classNo<='2999'));--创建一个学号的检查约束
alter table stud add constraint un_stuname unique(stuname);--添加唯一约束
create table scores(
ID number,--ID
term varchar2(2) not null, --学期S1或S2
stuid varchar2(7) not null, --学号
examNo varchar2(7) not null,--考号
writtenScore number(4,1)not null,--笔试成绩
labscore number(4,1) not null--机试成绩
)
select * from scores;
alter table scores add constraint ck_scores_term check
(term = 'S1'or term = 'S2');--创建学期约束
alter table scores add constraint fk_scores_stud_stuid foreign key
(stuid)references stud(stuid);--外键约束定义
--复制表结构
create table student as select * from stud where 1=2;
table created
select * from student;
--插入数据
insert into stud values('s100102','林冲','男',22,2, to_date('2012-10-22 12:30:10','YYYY-MM-DD HH24:mi:ss'),
'西安','1001'
)
--模糊查询
--模糊查询使用like关键字通过字符匹配检索出所需要的数据行。
--字符匹配操作可以使用通配符“%”和“_”
--%:表示零或者多个任意的字符
--_:表示一个任意字符
--语法是:like'字符串'[ESCAPE'字符']。匹配的字符串中,ESCAPE后面的“字符”作为转义字符
--minus(补集),返回第一个查询出的记录减去第二个查询检索出的记录之后剩下的记录。
select deptNo from dept minus select deptNo from emp;
--union(并集),返回各个查询的所有记录,不包括重复记录。
--用union插入多条数据
insert into dept
select 50,'公关部','台湾'from dual
union
select 60,'研发部','西安' from dual
union
select 70,'培训部','西安' from dual
--union All(并集),返回各个查询的所有记录,包括重复记录
--intersect (交集),返回两个查询共有的记录
--内连接
select e.ename,e.job,e.sal,d.dname,
from emp e,dept d
where e.deptno=d.deptno
and e.sal>2000;
select e.ename,e.job,e.sal,d.dname
from emp e inner join dept d on e.deptno=d.deptno
where e.sal>2000;
--外连接
select e.ename,e.job,e
.sal,d.dname
from emp e,dept d
where e.deptno(+)=d.deptno
--(+):在条件中出现在左边指右外连接,出现在右边指左外连接。
--标准写法
select e.ename,e.job,e.sal,d.dname
from emp e right outer join dept d on e.deptno=d.deptno
--高级查询中要注意:
--distinct 消去重复
--in 或
--between...and...在...之间
-----------------子查询-----------------------
--1.单行子查询:不向外部返回结果,或者只返回一行结果
select ename,job,sal from emp
where deptno=(select deptno from dept where dname='sales');--内部查询的结果作为外部查询的条件
--如果内部查询不返回任何记录,则外部条件中字段deptno与null比较永远为假
--也就是说外部查询不返回任何结果
--在单行子查询中外部查询可以使用=,>,<,<=,>=,<> 等比较运算符
--内部查询返回的结果必须与外部查询条件的字段(deptno)匹配
--如果内部查询返回多行结果则出现错误
--关键字any,any放在比较运算符后面,表示“任意”的意思。
--any子查询
select ename,job,sal from emp
where sal
---------- ALL 子查询--------
---All与关系操作符一起使用,表示与子查询中所有元素比较。
select ename,job,sal from emp
where sal>All(select sal from emp where job='salesman');
--- >All:比子查询结果中所有值还要大,也就是说,比子查询结果中最大值还要大
---
--2.多行子查询:向外部返回零行、一行或者多行结果
-------ROWID------------
---表中的每一行在数据库中都一个物理地址,rowid伪列返回的就是该行的物理地址
---使用rowid可以快速的定位表中的某一行。rowid值可以唯一的标示表中的一行。
----由于rowid返回的是该行的物理地址,因此使用rowid可以显示行是如何存储的。
select rowid,stuname from stud;
------rownum------
---在查询的结果集中,rownum 为结果集中每一行标识一个行号,第一行返回1,依次类推
----通过rownum 伪列可以限制查询结果集中返回的行数
select rownum ,ename,job,sal,from emp where rownum<=5;
--查询出工资最高的前5名员工的姓名,工作,工资
select rownum ,T.* from
(select ename,job,sal
from emp order by sal desc)T --T是子查询的别名,这里的ROWNUM 是第二次查询后的rownum
where rownum <=5;
-----rownum 分页
--查询出表emp中第5条和第10条之间的记录
select * from (select rownum r,ename,job,sal
from emp where rownum<=10 )
where r>5;
--内部查询中得到的rownum 并且用别名R记录,供外层条件使用
--
内部查询的rownum,与外出的rownum列是平等的两列
--使用的R是内层产生的rownum,在外层看来,内层查询的rownum是正常的一列
-------Oracle-函数--------
--1.单行函数:对每一个函数应用在表的记录中时,只能输入一行结果,返回一个结果
---常用的单行函数有:
--字符函数:对字符串操作。
---数字函数:对数字进行计算,返回一个数字
---转换函数:可以将一种数据类型转换为另一种数据类型
----日期函数:对日期和时间进行处理
---2.聚合函数:聚合函数同时可以对多行数据进行操作,并返回一个结果。
--比如 SUM(x)返回结果集中X列的总合。
------字符函数示例----
select ASCII('s')from dual--返回字符的ascii码
select concat('hello','world')from dual--连接字符串
select instr('hello world','o')from dual--在字符串中查找字符 可以指定从哪里开始
select length('hello')from dual--返回字符的长度
select lower('hHILO')from dual--转换为小写
select upper('hello')from dual--转换为大写
select ltrim('===HELLO===','=')from dual--把x左边截去‘=’字符串,缺省就截去空格
select '=='||ltrim(' HELLO===')from dual--- 把字符串左边加上‘==’字符串
select rtrim('---HELLO---','-')from dual----把字符串右边截去'-' 缺省就截去空格
select trim ('-'from'---Hello---')from dual---把字符串两边的‘-’截去
select replace('ABCDE','CD','AAA')from dual--在字符串中查找‘CD’并替换为‘AAA’
select substr('ABCDE',2)from dual---返回字符串,从2开始,缺省长度 默认到结尾
select substr('ABCDE',2,3)from dual---返回字符串,从2开始截取3个字符的长度。
select substr('100.000000',0,6)||'%' from dual
-------数字函数------------
SELECT ABS(-3) from dual---绝对值
select acos(1) from dual---反余弦
select cos(1)from dual--余弦
select ceil(5.4)from dual---大于或等于5.4的最小值
select floor(5.8)from dual---小于或等于5.8的最大值
select log(2,4)from dual---2为底4的对数
select mod(8,3)from dual---8除3的余数
select power(2,3)from dual---2的3次幂
select round(3.456,2)from dual---在第二位四舍五入
select sqrt(4)from dual--4的平方根
select trunc(3.456,1)from dual--数字在第2位截断
---日期函数-------
--1.add_month(d,n)在某个日期d上 加上指定的月数n,返回计算后的新日期。
select sysdate,add_months(sysdate,5)from dual
st_day(d)返回指定日期当月的最后一天
select sysdate,last_day(sysdate)from dual
--3.round(d[,fmt]) 返回一个以fmt为格式的四舍五入的日期值,d的日期,
--fmt是格式模型。默认为DDD,某月中的某天
select sysdate,round(sysdate),round(sysdate,'day'),
round(sysdate,'month'),round(sysdate,'year')from dual
--4.extract(fmt from d)提取日期中的特定部分
---fmt为:year,month,day,hour,mi
nute,second.
--其中year,month,day可以为date类型匹配,也可以与timestamp类型匹配;
--但是hour,minute,second必须与timestamp类型匹配
select sysdate "date",
extract(year from sysdate)"year",
extract(month from sysdate)"month",
extract(day from sysdate)"day",
extract(hour from systimestamp)"hour",
extract(minute from systimestamp)"minute",
extract(second from systimestamp)"second"
from dual;
------转换函数-----
--1.to_char(d|n[,fmt])
---把日期和数字转换为制定格式的字符串。fmt是格式化字符串,
select to_char(sysdate,'YYYY"年"MM"月"DD"日"HH24:mi:ss')"date"from dual;
---在格式化字符串中,使用双引号对非格式化字符进行引用
--2.to_date(x[,fmt])
--把一个字符串以fmt格式转换为一个日期类型
--3.to_number(x[,fmt])
--把一个字符串以fmt格式转换为一个数字。
select to_number('-$12,345.67','$99,999.99')"num"from dual
--------其他单行函数
--1.nvl(x,value) 如果x为空,返回value,否则返回X
select ename,job,sal,nvl(comm,100)from emp where sal<2000;
--2.nvl2(x,value1,value2) 如果x非空,返回value1,否则返回value2
select ename,job,sal,nvl2(comm,comm+100,200)"comm"
from emp where sal<2000;
--------聚合函数-----
---avg 平均值
---sum 求和
----min max 最小值,最大值
----count 数据统计
----------oracle 数据库对象
---create 创建
---alter 修改
----drop 删除操作
--同义词:就是给数据库对象一个别名
--序列:oracle中实现增长的对象
--视图; 预定义的查询,作为表一样的查询使用,是一张虚拟的表
---索引:对数据库表中的某些列进行排序,提高查询效率
--语句结构:同义词(sysnonym)
create [or replace][public]sysnonym[schema.]synonym_name for [schema.]object_name;
select * from ceis.stud;
--创建一个用户xiaomei,该用户拥有connect角色和resource角色
--CONN system/manage@orcl;
create user zhangsan identified by 123456;
grant connect to zhangsan;
grant resource to zhangsan;
grant create synonym to zhangsan;
grant all on EMP to zhangsan;
create synonym mystud for ceis.stud;
user zhangsan
select * from mystud;
select * from zhangsan.mystud;
----删除同义词
drop[public]synonym[schema.]sysnonym_name
--同义词的删除只能被拥有同义词对象的用户或者管理员删除
--此命令只能删除同义词,不能删除同义词下的源对象
---------序列----------sequence-------
---是用来生成连续的整数数据对象,序列常常用来作为主键中增长列
--序列中的可以升序生成,也可以降序生成
create sequence seq_stud
start with 1001--从某个数开始
increment by 1--增长数
maxvalue 1999--最大值
minvalue 1001--最小值
cycle-- 表示如果升序达到最大值时从最小值开始,反之从最大值开始
cache 30--当
内存中的序列号用完的时候,系统再生成一组新的序列号,并保存在缓存中
--这样提高生成序列号的效率
select seq_stud.currval from dual;
--currval 是当前的序列号
--nextval 是下一个序列号
----使用alter sequence 可以修改序列,但有如下限制
--1.不能修改序列的初始值
--2。最小值不能大于当前值
--3、最大值不能小于当前值
--使用drop sequence 命令可以删除一个序列对象
---------视图----------
---1.视图(view)实际上是一张或者多张表上的预定义查询
--这样就可以对最终用户屏蔽建表时底层的基表
--2.可以将复杂的查询保存为视图,可以对最终用户屏蔽一定的复杂性
--3.限制某个视图只能访问基表中的部分或者部分行的特定数据
--这样可以实现一定的安全性
--4.从多张基表中按一定的业务逻辑抽出用户关心的部分,形成一张虚拟表
create or replace force VIEW stud3
as
select * from stud
with read only
select * from stud3;
--drop view 可以删除视图
--------------------索引--index--------------
--oracle数据库会为表的主键和包含唯一约束的列自动创建索引。索引可以
--提高查询的效率,但是在数据增删改时需要更新索引
create unique index uq_ename_idx on emp(ename);--创建唯一索引
create index idx_sal on emp(sal);---创建列索引
create index idx_job_lower on emp(lower(job));--将job转换为小写后创建索引
--------group by 子句-------
create table sales(
emoid number, --雇员ID
depid number, --部门ID
area varchar2(20), --区域
salenum number --销售额
)
select * from sales;
insert into sales values (1,1,'china',10);
insert into sales values (2,1,'china',10);
insert into sales values (3,1,'china',10);
insert into sales values (3,1,'china',10);
insert into sales values (3,1,'china',10);
insert into sales values (1,1,'china',10);
insert into sales values (4,2,'china',10);
insert into sales values (4,2,'china',10);
insert into sales values (5,3,'us',10);
insert into sales values (5,3,'us',10);
--- 按部门统计销售额
select depid ,sum(salenum) from sales group by depid;
--按部门统计销售额,并且只显示销售总额小于30的部门及销售额(使用having子句)
select depid,sum(salenum) as"销售额 "from sales group by depid
having sum(salenum)<30;
--where 和 having 子句都是用来筛选数据,但是where 是针对原数据进行筛选,
--而having 子句只是针对汇总后的结果进行筛选
--所以在需求二的例子中,想要对销售进行过滤只能使用having子句
------扩展用法
create table testgroup(
a varchar2(5),
b varchar2(5),
c varchar2(5),
n number
)
select * from testgroup
insert into testgroup values('a1','b1','c1',10);
insert into testgroup values('a1','b1','c1',20);
select a,b,c ,sum(n) total from tes
tgroup group by a,b,c;
---使用rollup操作符------------
--卷起,汇总的意思,他可以在使得在其括号中的字段,按从右到左的顺序分别
--group 后显示,类似我们用多个group by语句 ,然后union all起来
--我们把针对 上面的测试表,使用rollup操作符,看看效果
select a,b,c,sum(n) total from testgroup group by rollup(a,b,c);
--cube操作符
--cube是立方 可以对操作符内的字段,进行遍历组合,例如cube(a,b,c)
--就会出来如下的混合
select a,b,c,sum(n) total from testgroup group by cube(a,b,c);
--使用grouping(filed)函数
----我们通过rollup或者cube对汇总进行了汇总,汇总后的结果往往要传送
--到应用程序端,在应用程序端我们必须要有一个依据来判断某行数据
--是不是按照rollup或cube进行汇总,grouping函数可以用来产生这个依据,
--他可以接收一个参数,判断该参数是否为null,是则返回1,否则返回0,
--我们可以据此来判断该是否按某列进行汇总统计的
select grouping(a)ca,grouping(b)cb,grouping(c)cc,
a,b,c,sum(n)
from testgroup group by rollup(a,b,c);
--grouping_id(filed1,file2,…)函数
--假如我们要对某testgroup进行分组统计,并且过滤掉不包括小计或总计的行,
--这时grouping_id就有用武之地了,我们可以利用grouping_id的值结合having子句,
--通过判断grouping_id是否大于0来过滤掉不需要的行。
select grouping(a) ca,grouping(b) cb,grouping_id(a,b) caandb, a,b,sum(n)
from testgroup group by rollup(a,b) having grouping_id(a,b)>0;
--------oracle SQL 语句优化-------------------
--1,选择最有效率的表名顺序(只是基于规则的优化器重有效)
--oracle的解析器按照从右到左的顺序处理from子句中的表名,from子句中写在
--最后的表(基础表 driving table )将被最优先处理,在from子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。
--如果有三个以上的表连接查询,拿就选择交叉表(intersection table)作为基表,交叉表是指那个被其他表所引用的表
--2,where子句中的连接顺序:
--oracle采用自上而下的顺序解析where子句,根据这个原理,表之间的连接必须写在其他where条件之前,
--那么可以过滤掉最大数量记录的条件必须写在where子句的末尾
--3,select子句中避免使用“*”:
--oracle在解析的过程中,会将* 依次转化成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间
--4,减少访问数据库的次数
--5,在SQL*PLUS,SQL*FROM和pro*c中重新设置ARRAYSIZE参数,可以增加每次数据库访问的检索数量,
--6,使用decode函数来减少处理时间:
--使用decode函数可以避免重复扫描相同记录或重复连接相同的表
---decode的用法-----------------------
----
--decode(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)
--该函数的含义如下: IF 条件=值1 THEN RETURN(翻译值1) ELSIF 条件=值2 THEN RETURN(翻译值2)
-- ...... ELSIF 条件=值n THEN RETURN(翻译值n)
-- ELSE RETURN(缺省值) END IF
--1比较大小
select decode(sign(变量1-变量2),-1,变量1,变量2) from dual;
--取较小值 sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1
--例如: 变量1=10,变量2=20 则sign(变量1-变量2)返回-1,
--decode 解码结果为“变量1”,达到了 取较小值的目的
--7.整合简单,无关联的数据库访问:
--如果你有几个简单的数据库查询语句,你可以把他们整合到一个查询中(即使它们之间没有关系)
--8,删除重复记录:
--最高效的的删除重复记录方法(因为使用了ROWID)例子:
delete from emp e where rowid>(select min(x.rowid))from emp x where x.emp_no=e.emp_no);
--9,用truncate替代DELETE
--当删除表中的记录时,在通常情况下,回滚(rollback segments)用来存放可以被回复的信息。
--如果你没有commit事务,oracle 会将数据恢复到删除之前的状态(准确的说是恢复到执行删除命令之前的状况)
--而当运用了truncate时,回滚段不再存放任何可被恢复的信息,当命令运行后,数据不能被恢复。因此很少的资源被
--调用,执行时间也会很短
--10,尽量多用commit
--只要有可能,在程序中尽量多用commit 这样程序的性能得到了提高,需求也会因为commit所释放的资源而减少:
--commit所释放的资源
--a,回滚段上用于恢复数据的信息
--b,被程序语句获得的锁
--c。redo log buffer 中的空间
--d。oracle为管理上述3种资源中的内部花费
----11.用where子句替换having子句
--避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤.
--这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.
--(非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,
--因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,
--按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,
--在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。
--在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,
--只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,
--就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的
作用时间是在计算之前就完成的,
--而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。
--系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,
--计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,
--首先要明白这个条件应该在什么时候起作用,然后再决定放在那里
--12.减少对表的查询
--在含有子查询的SQL语句中,要特别注意减少对表的查询
select tab_name from tables where(tab_name,db_ver)=(select tab_name,db_ver from tab_columns where version=604)
---13.通过内部函数提高SQL效率:
--复杂的SQL往往会牺牲了执行效率,能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的
---14.使用表的别名
--当在sql语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上,这样一来,就可以减少解析的时间并减少哪些
--由Column歧义引起的语法错误
---15.使用EXISTS替代IN,用NOT EXISTS替代NOT IN:
--在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行连接,在这种情况下
--使用Exists(或NOT EXISTS)通常将提高查询的效率,在子查询中 NOT IN 子句将执行一个内部的排序和合并
--无论在那种情况下,NOT IN 都是最低效的(因为它对子查询中的表执行了一个全表遍历)、
--为了避免使用NOT IN 我们可以把它改写成外连接(Outer Joins)或NOT EXISTS
--高效
select * from emp where empno>0 and exists(select 'x'from dept where dept.deptno=emp.deptno and loc='MELB')
--低效
select * from emp where empno>0 and deptno in (select deptno from dept where loc='MELB');
----16.识别低效执行的SQL语句
--虽然目前各种关于SQL优化的图形工具层出不但是写出自己的SQL工具来解决问题始终是一个最好的方法:
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;
---17.用索引来提高效率
--索引是表的一个概念部分,用来提高检索数据的效率,oracle使用了一个复杂的自平衡B-tree
--结构,通常,通过索引查询数据比全表扫描要快。当oracle找出执行查询和update语句的最佳路径时
--oracle优化器将使用索引。同样在连接多个表的时候使用索引页将提高效率,另一个使用索引的好处
--它提供了主键(primary key)的唯一性验证。那些long或LONG RAW数据类型,你可以索引
--几乎所有的列,通常,在大型表中使用索引
特别有效。当然,你也会发现,在扫描小表时
--,使用索引同样能够提高效率,虽然使用索引能得到查询效率的提高,但是我们也注意到它的代价
--。索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时, 索引本身也会被修改.
-- 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O .
--因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。定期的重构索引是有必要的.:
--ALTER INDEX
--18.用exists 替换distinct
--当提交一个包含一对多表信息(比如部门表和雇员表)的查询时 避免在select子句使用
--distinct 一般可以考虑用exist替换,EXISTS让查询更为迅速,因为RDBMS模块将在子查询的条件一旦满足后,立即返回结果
--例子
select distinct dept_no,dept_name from dept d,emp e
where d.deptno=e.deptno--低效
select dept_no,dept_name from dept d
where exists(select 'x' from emp e
where e.dept_no=d.dept_no);--高效
--19.SQL语句用大写的;因为oracle总是先解析SQL语句,把小写的字母转换成大写的再执行
--20.在java中尽量少用连接符"+"连接字符串
--21.避免在索引列上使用NOT
--我们要避免在索引列上使用NOT,NOT会产生和在索引列上使用函数相同的影响。当oracle“遇到”NOT
--它就会停止使用索引转而执行全表扫描
--22.避免在索引上使用计算
--where子句中,如果索引列是函数的一部分。优化器将不使用索引而使用全表扫描
--低效
select ... from dept where SAL*12>25000;
--高效
select ... from dept where sal>25000/12;
--23.用>=替代>
--高效
select* from emp where deptno>=4;
--低效
select * from emp where deptno>3;
--两者的区别在于,前者DBMS 将直接跳到第一个dept等于4的记录而后者将首先定位到
--deptno=3的记录并且向前扫描到第一个dept大于3的记录
--24.用union替换or(适用于索引列)
--25.用in来替换or
--26.避免在索引列上使用is null 和not null
--27.总是使用索引的第一个列
--如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,
--优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,
--优化器使用了全表扫描而忽略了索引
--28.用where 替代order by
ORDER BY-- 子句只在两种严格的条件下使用索引.
ORDER BY --中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.
ORDER BY --中所有的列必须定义为非空.
WHERE --子句使用的索引和ORDER BY子句中所使用的索引不能并列.
--29.避免改变索引列的类型
--当比较不同数据类型数据时,oracle自动对列进行简单的类型转
换。
--假设empno是一个数值类型的索引列。
--SELECT … FROM EMP WHERE EMPNO = ‘123' 实际上,经过ORACLE类型转换, 语句转化为:
--SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 幸运的是,类型转换没有发生在索引列上,
--索引的用途没有被改变. 现在,假设EMP_TYPE是一个字符类型的索引列.
SELECT … FROM EMP WHERE EMP_TYPE = 123
--这个语句被ORACLE转换为:
SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123
--因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换,
--最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型
--30.需要当心的where子句:
--某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. 在下面的例子里,
--(1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中.
--(2) ‘||'是字符连接函数. 就象其他函数那样, 停用了索引.
--(3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引.
--(4)相同的索引列不能互相比较,这将会启用全表扫描.
--31.a.如果检索数据量超过30%的表中记录数。使用索引将没有显著的效率提高
--b.在特定情况下,使用索引也许会比全表扫描慢,但这是同一个数量级上的区别,
--而通常情况下,使用索引比全表扫描要快几倍乃至几千倍
--32.避免使用消耗资源的操作
--带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能.
-- DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的
--SQL语句都可以用其他方式重写. 如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT
--也是可以考虑的, 毕竟它们的可读性很强
--33.优化group by
--提高group by 语句的效率,可以将不需要的记录在group by 之前过滤掉。下面两个查询返回相同结果
--但第二个明显快了许多
--低效:
SELECT JOB , AVG(SAL) FROM EMP GROUP by JOB HAVING JOB = ‘PRESIDENT' OR JOB = ‘MANAGER'
--高效:
SELECT JOB , AVG(SAL) FROM EMP WHERE JOB = ‘PRESIDENT'OR JOB = ‘MANAGER' GROUP by JOB