oracle基本语句


 

--以下代码是对emp表进行显示做设置

 

col empno for 9999;

col ename for a10;

col job for a10;

col mgr for 9999;   

col hiredate for a12;

col sal for 9999;

col comm for 9999;

col deptno for 99;

set pagesize 20;

col tname for a20;

set pagesize 80;

 

--创建新表new_emp,复制emp表中的结构和数据到new_emp表中

 

create table copy_emp

as

select * from emp;

 

create table copy_copy_emp

as

select * from emp;

 

*/

 

启动如下二个服务:【OracleServiceORCL(设置为手动启动)OracleOraDb11g_home1TNSListener(设置为自动启动端口1521)

类似于MySQL中的:use数据库名,即use orcl;

即启动当前数据库名:orcl

 

 

-------------------------------------------------------------------------------------select

 

 

使用password命令,为scott用户名修改新密码,以字母开头,但提倡使用tiger

password

旧口令:tiger

新口令:abc123

再次输入新口令:abc123

 

退出sqlplus工具

exit

 

查询当前用户是谁

show user;

 

查询scott用户下的所有对象,使用tab表,tab表每个用户都有

select * from tab;

 

设置显示的列宽(字符型varchar2、日期型date),10个宽度位,a表示字符型,大小写均可

column ename format a12;

column hiredate format a10;

 

设置显示的列宽(数值型number),9表示数字型,一个9表示一个数字位,四个9表示四个数字位,只能用9

column empno format 9999;

column mgr format 9999;

column sal format 9999;

column comm format 9999;

column deptno format 9999;

 

设置一页显示80个条记录的高度

set pagesize 80;

 

使用/杠,执行最近一次的SQL语句

/

 

清屏,属于SQL*PLUS工具中的命令

host cls;

 

查询emp表的结构

desc emp;

 

查询emp表的所有内容,*号表示通配符,表示该表中的所有字段,但*号不能和具体字段一起使用

select * from emp;

select empno,ename,sal,deptno from emp;

 

查询emp表的员工编号,姓名,工资,部门号,列名,大小写不敏感,但提倡大写

select empno "编号",ename "姓名",sal "工资",deptNO "部门号" FROM Emp;

 

查询emp表的不重复的工作

select distinct job from emp;

 

查询员工的编号,姓名,月薪,年薪(月薪*12)

select empno,ename,sal,sal*12 "年薪" from emp;

 

查询员工的编号,姓名,入职时间,月薪,年薪,年收入(年薪+奖金)

select empno "编号",ename"姓名",hiredate "入职时间",sal "月薪",sal*12 "年薪",sal*12+comm "年收入" from emp;

如果结果为null,在sqlplus客户端工具中,是不显示null这个值的

 

解决null的问题,使用NVL()函数,NVL(a,b):如果aNULL,用b替代;如果a是非NULL,就不用b替代,直接返回a的值\

select NVL(null,10) from emp;结果有14行记录

select NVL(null,10) from dual;结果有1行记录

select empno "编号",ename"姓名",hiredate "入职时间",sal "月薪",sal*12 "年薪",sal*12+NVL(comm,0) "年收入"

from emp;

注意:null与具体数字运算时,结果为null

 

使用列别名,查询员工的编号,姓名,月薪,年薪,年收入(年薪+奖金)AS大小写都可且可以省略AS,别名用双引号

select empno AS "编号",ename as "姓名",sal "月薪"

from emp;

select empno AS 编号,ename as姓名,sal月薪

from emp;

区别

select empno AS "编号",ename as姓名,sal "月    薪"

from emp;

不加双引号的别名不能有空格;加了双引号的别名可以有空格

要加只能加双引号,不能加单引号,因为在oracle中单引号表示字符串类型或者是日期类型

列名不能使用单引号,因为oracle认为单引号是字符串型或日期型

 

使用dual哑表或者伪表,使用字符串连接符号||,输出"hello world",在oraclefrom是必须写的

select 'hello' || ' world' "结果" from dual;

 

使用sysdate,显示系统当前时间,在默认情况下,oracle只显示日期,而不显示时间,格式:26-4-15

select sysdate from dual;

 

使用字符串连接符号||,显示如下格式信息:****的薪水是****美元

select ename || '的薪水是' || sal || '美元'

from emp;

 

使用spool命令,保存SQL语句到硬盘文件e:/oracle-day01.sql,并创建sql文件

spool e:/oracle-day01.sql;

 

使用spool off命令,保存SQL语句到硬盘文件e:/oracle-day01.sql,并创建sql文件,结束语句

spool off;

 

使用@命令,将硬盘文件e:/crm.sql,读到orcl实例中,并执行文件中的sql语句

@ e:/crm.sql;

 

使用--符号,设置单行注释

--select * from emp;

 

使用/* */符号,设置多行注释

/*

select

*

from

emp;

*/

总结:你学过的所有技术中,关于注释的符号

html:

css:

js:

xml:

jsp:

mysql:

oracle:

java:

 

SQL语句的特点

1)是SQL92/99ANSI官方标准,只要按照该标准来写,在任何的关系型数据库中都可以直接执行

2SQL语句的关健字不能简写,例如:selectwherefrom

3)大小写不敏感,提倡大写

4)能够对表数据进行增删改查操作

5)必须以分号结束

6)通常称做语句

 

SQLPLUS命令的特点

1)是oracle自带的一款工具,在该工具中执行的命令叫SQLPLUS命令

2SQLPLUS工具的命令中的关健字可以简写,也可以不简写,例如:col ename for a10;

3)大小写不敏感,提倡大写

4)不能够对表数据进行增删改查操作,只能完成显示格式控制,例如:设置显示列宽,清屏,记录执行结果

5)可以不用分号结束,也可以用分号结束,个人提倡不管SQLSQLPLUS,都以分号结束

6)通常称做命令,是SQLPLUS工具中的命令

注意:SQLPLUS命令是SQLPLUS工具中特有的语句

 

单引号出现的地方如下:

1)字符串型,例如:'hello' || ' world'

2)日期型,例如'25-4-15'

 

双引号出现的地方如下:

1)列别名,例如:sal*12 "年 薪",或sal*12 年薪,个人提倡用""双引号作列别名

            

 

-------------------------------------------------------------------------------------where

 

 

查询emp表中20号部门的员工信息

select * from emp where deptno = 20;

 

查询姓名是SMITH的员工,字符串使用'',内容大小写敏感

select * from emp where ename = 'SMITH';

总结:你所学过的技术中,哪些是大小写敏感,哪些是大小写不敏感

 

查询19801217日入职的员工,注意oracle默认日期格式(DD-MON-RR表示2位的年份)

select * from emp where hiredate = '17-12-80';

 

查询工资大于1500的员工

select * from emp where sal > 1500;

 

查询工资不等于1500的员工【!=<>

select * from emp where sal <> 1500;

 

查询薪水在13001600之间的员工,包括13001600

select * from emp where (sal>=1300) and (sal<=1600);

select * from emp where sal between 1300 and 1600;

 

查询薪水不在13001600之间的员工,不包括13001600

select * from emp where sal NOT between 1300 and 1600;

 

查询入职时间在"1981-2-20""1982-1-23"之间的员工

select * from emp where hiredate between '20-2-81' and '23-1-82';

注意:

1)对于数值型,小数值在前,大数值在后

2)对于日期型,年长值在前,年小值在后

 

查询20号或30号部门的员工,例如:根据ID号,选中的员工,批量删除

select * from emp where (deptno=20) or (deptno=30);

select * from emp where deptno in (30,20);

 

查询不是20号或30号部门的员工

select * from emp where deptno NOT in (30,20);

 

查询姓名以大写字母S开头的员工,使用%表示0个,1个或多个字符

select * from emp where ename like 'S';

等价

select * from emp where ename = 'S';

select * from emp where ename like 'S%';

 

注意:

凡是精确查询用=符号

凡是不精确查询用like符号,我们通常叫模糊查询

 

查询姓名以大写字母N结束的员工

select * from emp where ename like '%N';

 

查询姓名第一个字母是T,最后一个字母是R的员工

select * from emp where ename like 'T%R';

 

查询姓名是4个字符的员工,且第二个字符是I,使用_只能表示1个字符,不能表示0个或多个字符

select * from emp where ename like '_I__';

 

插入一条姓名为'T_IM'的员工,薪水1200

insert into emp(empno,ename) values(1111,'T_IM');

 

查询员工姓名中含有'_'的员工,使用\转义符,让其后的字符回归本来意思【like '%\_%' escape '\'

select * from emp where ename like '%\_%' escape '\';

 

插入一个姓名叫'的员工

insert into emp(empno,ename) values(2222,'''');

 

插入一个姓名叫''的员工

insert into emp(empno,ename) values(2222,'''''');

 

查询所有员工信息,使用%%%

select * from emp;

select * from emp where ename like '%';

select * from emp where ename like '%_%';

 

查询佣金为null的员工

select * from emp where comm is null;

注意:null不能参数=运算

      null能参数number/date/varchar2类型运算

 

查询佣金为非null的员工

select * from emp where comm is not null;

 

查询无佣金且工资大于1500的员工

select *

from emp

where (comm is null) and (sal>1500);

 

查询工资是150030005000的员工

select *

from emp

where sal in (4000,10000,1500,3,300,3000,5000);

 

查询职位是"MANAGER"或职位不是"ANALYST"的员工(方式一,使用!=<>

select *

from emp

where (job='MANAGER') or (job<>'ANALYST');

 

查询职位是"MANAGER"或职位不是"ANALYST"的员工(方式二,使用not

select *

from emp

where (job='MANAGER') or (not(job='ANALYST'));

 

 

-------------------------------------------------------------------------------------order by

 

 

查询员工信息(编号,姓名,月薪,年薪),按月薪升序排序,默认升序,如果月薪相同,按oracle内置的校验规则排序

select empno,ename,sal,sal*12

from emp

order by sal asc;

 

查询员工信息(编号,姓名,月薪,年薪),按月薪降序排序

select empno,ename,sal,sal*12

from emp

order by sal desc;

 

查询员工信息,按入职日期降序排序,使用列名

select empno,ename,sal,hiredate,sal*12 "年薪"

from emp

order by hiredate desc;

 

order by后面可以跟列名、别名、表达式、列号(从1开始,在select子句中的列号)

列名:

select empno,ename,sal,hiredate,sal*12 "年薪"

from emp

order by hiredate desc;

 

别名:

select empno,ename,sal,hiredate,sal*12 "年薪"

from emp

order by "年薪" desc;

 

表达式:

select empno,ename,sal,hiredate,sal*12 "年薪"

from emp

order by sal*12 desc;

 

列号,从1开始:

select empno,ename,sal,hiredate,sal*12 "年薪"

from emp

order by 5 desc;

 

查询员工信息,按佣金升序或降序排列,null值看成最大值

select * from emp order by comm desc;

 

查询员工信息,对有佣金的员工,按佣金降序排列,当order by where 同时出现时,order by在最后

select *

from emp

where comm is not null

order by comm desc;

 

查询员工信息,按工资降序排列,相同工资的员工再按入职时间降序排列

select *

from emp

order by sal desc,hiredate desc;

 

select *

from emp

order by sal desc,hiredate asc;

注意:只有当sal相同的情况下,hiredate排序才有作用

 

查询20号部门,且工资大于1500,按入职时间降序排列

select *

from emp

where (deptno=20) and (sal>1500)

order by hiredate desc;

 

select * from emp where deptno in (10,20,30,50,'a');

 

-------------------------------------------------------------------------------------单行函数

 

 

单行函数:只有一个参数输入,只有一个结果输出

多行函数或分组函数:可有多个参数输入,只有一个结果输出

 

测试lower/upper/initcap函数,使用dual哑表

select lower('www.BAIdu.COM') from dual;

select upper('www.BAIdu.COM') from dual;

select initcap('www.BAIdu.COM') from dual;

 

测试concat/substr函数,从1开始,表示字符,不论中英文

select concat('hello','你好') from dual;正确

select concat('hello','你好','世界') from dual;错误

select 'hello' || '你好' || '世界' from dual;正确

select concat('hello',concat('你好','世界')) from dual;正确

select substr('hello你好',5,3) from dual;

5表示从第几个字符开始算,第一个字符为1,中英文统一处理

3表示连续取几个字符

 

测试length/lengthb函数,编码方式为UTF8/GBK(赵君),一个中文占3/2个字节长度,一个英文一个字节

select length('hello你好') from dual;

select lengthb('hello你好') from dual;

 

测试instr/lpad/rpad函数,从左向右找第一次出现的位置,从1开始

select instr('helloworld','o') from dual;

注意:找不到返回0

      大小写敏感

select LPAD('hello',10,'#') from dual;

select RPAD('hello',10,'#') from dual;

 

测试trim/replace函数

select trim(' ' from '  he  ll                ') from dual;

select replace('hello','l','L') from dual;

 

测试round/trunc/mod函数作用于数值型

select round(3.1415,3) from dual;

select trunc(3.1415,3) from dual;

select mod(10,3) from dual;

 

当前日期:sysdate = 26-4-15

 

测试round作用于日期型(month

select round(sysdate,'month') from dual;

 

测试round作用于日期型(year

select round(sysdate,'year') from dual;

 

测试trunc作用于日期型(month

select trunc(sysdate,'month') from dual;

 

测试trunc作用于日期型(year

select trunc(sysdate,'year') from dual;

 

显示昨天,今天,明天的日期,日期类型 +- 数值 = 日期类型

select sysdate-1 "昨天",sysdate "今天",sysdate+1 "明天" from dual;

 

以年和月形式显示员工近似工龄,日期-日期=数值,假设:一年以365天计算,一月以30天计算

select ename "姓名",round(sysdate-hiredate,0)/365 "天数" from emp;

 

使用months_between函数,精确计算到年底还有多少个月

select months_between('31-12-15',sysdate) from dual;

 

使用months_between函数,以精确月形式显示员工工龄

select ename "姓名",months_between(sysdate,hiredate) "精确月工龄" from emp;

 

测试add_months函数,下个月今天是多少号

select add_months(sysdate,1) from dual;

 

测试add_months函数,上个月今天是多少号

select add_months(sysdate,-1) from dual;

 

测试next_day函数,从今天开始算,下一个星期三是多少号【中文平台】

select next_day(sysdate,'星期三') from dual;

 

测试next_day函数,从今天开始算,下下一个星期三是多少号【中文平台】

select next_day(next_day(sysdate,'星期三'),'星期三') from dual;

 

测试next_day函数,从今天开始算,下一个星期三的下一个星期日是多少号【中文平台】

select next_day(next_day(sysdate,'星期三'),'星期日') from dual;

 

测试last_day函数,本月最后一天是多少号

select last_day(sysdate) from dual;

 

测试last_day函数,本月倒数第二天是多少号

select last_day(sysdate)-1 from dual;

 

测试last_day函数,下一个月最后一天是多少号

select last_day(add_months(sysdate,1)) from dual;

 

测试last_day函数,上一个月最后一天是多少号

select last_day(add_months(sysdate,-1)) from dual;

 

注意:

1)日期-日期=天数

2)日期+-天数=日期

 

 

-------------------------------------------------------------------------------------三大类型转换

 

 

oracle中三大类型与隐式数据类型转换

1varchar2变长/char定长-->number,例如:'123'->123

2varchar2/char-->date,例如:'25-4-15'->'25-4-15'

3number---->varchar2/char,例如:123->'123'

4date------>varchar2/char,例如:'25-4-15'->'25-4-15'

 

oracle如何隐式转换:

1=号二边的类型是否相同

2)如果=号二边的类型不同,尝试的去做转换

3)在转换时,要确保合法合理,否则转换会失败,例如:12月不会有32天,一年中不会有13

 

查询19801217日入职的员工(方式一:日期隐示式转换)

select * from emp where hiredate = '17-12-80';

 

使用to_char(日期,'"常量"')函数将日期转成字符串,显示如下格式:201504 25日 星期六

select to_char(sysdate,'yyyy" "mm""dd""day') from dual;

 

使用to_char(日期,'格式')函数将日期转成字符串,显示如格式:2015-04-25今天是星期六15:15:15

select to_char(sysdate,'yyyy-mm-dd"今天是"day hh24:mi:ss') from dual;

select to_char(sysdate,'yyyy-mm-dd"今天是"day HH12:MI:SS AM') from dual;

 

使用to_char(数值,'格式')函数将数值转成字符串,显示如下格式:$1,234

select to_char(1234,'$9,999') from dual;

 

使用to_char(数值,'格式')函数将数值转成字符串,显示如下格式:¥1,234select to_char(1234,'$9,999') from dual;

select to_char(1234,'L9,999') from dual;

 

使用to_date('字符串','格式')函数,查询19801217日入职的员工(方式二:日期显式转换)

select * from emp where hiredate = to_date('19801217','yyyy""mm""dd""');

select * from emp where hiredate = to_date('1980#12#17','yyyy"#"mm"#"dd');

select * from emp where hiredate = to_date('1980-12-17','yyyy-mm-dd');

 

使用to_number('字符串')函数将字符串‘123’转成数字123

select to_number('123') from dual;

 

 

注意:

select '123' + 123 from dual;246

select '123' || 123 from dual;123123

 

 

-----------------------------------

 

 

 

使用NVL(a,b)通用函数,统计员工年收入,NVL()作用于任何类型,即(number/varchar2/date)

通用函数:参数类型可以是numbervarchar2date类型

 

使用NVL2(a,b,c)通用函数,如果a不为NULL,取b值,否则取c值,统计员工年收入

 

使用NULLIF(a,b)通用函数,在类型一致的情况下,如果ab相同,返回NULL,否则返回a,比较1010.0是否相同

 

使用SQL99标准通用语法中的case表达式,将职位是分析员的,工资+1000;职位是经理的,工资+800;职位是其它的,工资+400

case 字段

     when 条件 then表达式1

     when 条件 then表达式2

     else 表达式n

end

 

使用oracle专用语法中的decode()函数,职位是分析员的,工资+1000;职位是经理的,工资+800;职位是其它的,工资+400

decode(字段,条件1,表达式1,条件2,表达式2,...表达式n)

 

单引号出现的地方如下:

1)字符串,例如:'hello'

2)日期型,例如:'17-12-80'

3to_char/to_date(日期,'YYYY-MM-DD HH24:MI:SS')

 

双引号出现的地方如下:

1)列别名,例如:select ename "姓 名" from emp

2to_char/to_date(日期,'YYYY""MM""DD"" HH24:MI:SS')

 

 

 

 

 

 

 

培训要求

 

1)掌握多行函数与分组操作

 

2)掌握多表查询与子查询

 

3)理解集合查询与掌握Oracle分页语法

 

4)理解创建、修改和删除表和表约束

 

 

-------------------------------------------------------------------------------------准备篇

 

 

col empno for 9999;

col ename for a10;

col job for a10;

col mgr for 9999;   

col hiredate for a12;

col sal for 9999;

col comm for 9999;

col deptno for 99;

set pagesize 20;

col tname for a20;

set pagesize 80;

 

 

-------------------------------------------------------------------------------------通用函数和条件判断函数

 

 

使用NVL(a,b)通用函数,统计员工年收入,NVL()作用于任何类型,即(number/varchar2/date)

通用函数:参数类型可以是numbervarchar2date类型

select ename,sal*12+NVL(comm,0) from emp;

 

使用NVL2(a,b,c)通用函数,如果a不为NULL,取b值,否则取c值,统计员工年收入

select ename,sal*12+NVL2(comm,comm,0) from emp;

 

使用NULLIF(a,b)通用函数,在类型一致的情况下,如果ab相同,返回NULL,否则返回a,比较1010.0是否相同

select NULLIF(10,'10') from dual;

 

使用SQL99标准通用语法中的case表达式,将职位是分析员的,工资+1000;职位是经理的,工资+800;职位是其它的,工资+400

case 字段

     when 条件1 then表达式1

     when 条件2 then表达式2

     else 表达式n

end

课后请参考<MySQL5.X的手册>-12.2这个章节

select ename "姓名",job "职位",sal "涨前工资",

       case job

    when 'ANALYST' then sal+1000

    when 'MANAGER' then sal+800

            else sal+400

       end "涨后工资"

from emp;

 

使用oracle专用语法中的decode()函数,职位是分析员的,工资+1000;职位是经理的,工资+800;职位是其它的,工资+400

decode(字段,条件1,表达式1,条件2,表达式2,...表达式n)

select ename "姓名",job "职位",sal "涨前工资",

       decode(job,'ANALYST',sal+1000,'MANAGER',sal+800,sal+400) "涨后工资"

from emp;

 

单引号出现的地方如下:

1)字符串,例如:'hello'

2)日期型,例如:'17-12-80'

3to_char/to_date(日期,'YYYY-MM-DD HH24:MI:SS')

 

双引号出现的地方如下:

1)列别名,例如:select ename "姓 名" from emp

2to_char/to_date(日期,'YYYY""MM""DD"" HH24:MI:SS')‘’号中的英文字符大小写不敏感

 

 

-------------------------------------------------------------------------------------多行函数

 

 

函数:oracle服务器先事写好的一段具有一定功能的程序片段,内置于oracle服务器,供用户调用

单行函数:输入一个参数,输出一个结果,例如:upper('baidu.com')->BAIDU.COM

多行函数:输入多个参数,或者是内部扫描多次,输出一个结果,例如:count(*)->14

 

统计emp表中员工总人数

select count(*) from emp;

*号适用于表字段较少的情况下,如果字段较多,扫描多间多,效率低,项目中提倡使用某一个非null唯一的字段,通常是主键

 

统计公司有多少个不重复的部门

select count(distinct deptno) from emp;

 

统计有佣金的员工人数

select count(comm) from emp;

注意:今天讲的这些多个行函数,不统计NULL

 

员工总工资,平均工资,四舍五入,保留小数点后0

select sum(sal) "总工资",round(avg(sal),0) "平均工资"

from emp;

 

查询员工表中最高工资,最低工资

select max(sal) "最高工资",min(sal) "最低工资"

from emp;

 

入职最早,入职最晚员工

select max(hiredate) "最晚入职时间",min(hiredate) "最早入职时间"

from emp;

 

多行函数:count/sum/avg/max/min

 

按部门求出该部门平均工资,且平均工资取整数,采用截断

select deptno "部门编号",trunc(avg(sal),0) "部门平均工资"

from emp

group by deptno;

 

(继续)查询部门平均工资大于2000元的部门

select deptno "部门编号",trunc(avg(sal),0) "部门平均工资"

from emp

group by deptno

having trunc(avg(sal),0) > 2000;

 

(继续)按部门平均工资降序排列

select deptno "部门编号",trunc(avg(sal),0) "部门平均工资"

from emp

group by deptno

having trunc(avg(sal),0) > 2000

order by 2 desc;          2表示第二个字段。

 

10号部门外,查询部门平均工资大于2000元的部门,方式一【having deptno<>10

select deptno,avg(sal)

from emp

group by deptno

having deptno<>10;

 

10号部门外,查询部门平均工资大于2000元的部门,方式二【where deptno<>10

select deptno,avg(sal)

from emp

where deptno<>10

group by deptno;

提倡

 

显示部门平均工资的最大值

select max(avg(sal)) "部门平均工资的最大值"

from emp

group by deptno;

 

思考:显示部门平均工资的最大值和该部门编号?

select max(avg(sal)) "部门平均工资的最大值",deptno "部门编号"

from emp

group by deptno;

错误

 

group by 子句的细节:

1)在select子句中出现的非多行函数的所有列,【必须】出现在group by子句中

2)在group by子句中出现的所有列,【可出现可不现】在select子句中

 

wherehaving的区别:

where

1)行过滤器

2)针对原始的记录

3)跟在from后面

4where可省

5)先执行

 

having

1)组过滤器

2)针对分组后的记录

3)跟在group by后面

4having可省

5)后执行

 

oracle中综合语法:

1select子句-----必须

2from子句-------必须,不知写什么表了,就写dual

3where子句------可选

4group by子句---可选

5having子句-----可选

6order by子句--可选,如果出现列名,别名,表达式,字段

 

 

-------------------------------------------------------------------------------------多表查询

 

 

员工表emp和部门表dept的笛卡尔集(笛卡尔集表=列数之和,行数之积,笛卡尔集表内中有些数据是不符合要求的)

select emp.ename,dept.dname

from emp,dept;

 

使用等值连接/内连接(只能使用=号),显示员工的编号,姓名,部门名,使用表别名简化

select emp.empno,emp.ename,dept.dname,dept.deptno

from emp,dept

where emp.deptno = dept.deptno;

 

使用非等值连接(不能使用=号,其它符号可以,例如:>=<=<>betwen and等),显示员工的编号,姓名,月薪,工资级别

select e.empno,e.ename,e.sal,s.grade

from emp e,salgrade s

where e.sal between s.losal and s.hisal;

 

内连接查询:只能查询出符合条件的记录

外连接查询:既能查询出符合条件的记录,也能根据一方强行将另一个方查询出来

 

使用外连接,按部门10,20,30,40号,统计各部门员工人数,要求显示部门号,部门名,人数

部门号 部门名        人数

10     ACCOUNTING    3

20     RESEARCH      5

30     SALES         6

40     OPERATIONS    0

 

等值连接/非等值连接/内连接:只会查询出多张表中,根据某个字段匹配,符合条件的记录,不符合条件的记录是不会存在的

 

左外连接[oracle专用的,不是SQL99规则]

select dept.deptno "部门号",dept.dname "部门名",count(emp.empno) "人数"

from dept,emp

where dept.deptno = emp.deptno(+)

group by dept.deptno,dept.dname;

 

右外连接:

select dept.deptno "部门号",dept.dname "部门名",count(emp.empno) "人数"

from dept,emp

where emp.deptno(+) = dept.deptno

group by dept.deptno,dept.dname;

 

使用左外连接,按部门10,20,30,40号,统计各部门员工人数,要求显示部门号,部门名,人数,且按人数降序排列

select dept.deptno "部门号",dept.dname "部门名",count(emp.empno) "人数"

from dept,emp

where dept.deptno = emp.deptno(+)

group by dept.deptno,dept.dname

order by 3 desc;

 

使用自连接,显示"SMITH的上级是FORD"这种格式

select users.ename || '的上级是' ||boss.ename

from emp users,emp boss

where users.mgr = boss.empno;

只有13条记录,不含有KING

 

基于上述问题,将KING的上级是“”显示出来

select users.ename || '的上级是' ||boss.ename

from emp users,emp boss

where users.mgr = boss.empno(+);

14条记录

注意:自连接也用到内连接和外连接

 

 

-------------------------------------------------------------------------------------子查询

 

 

子查询的作用:查询条件未知的事物

 

查询条件已知的问题:例如:查询工资为800的员工信息

查询条件未知的问题:例如:查询工资为20号部门平均工资的员工信息

一个条件未知的问题,可以分解为多个条件已知的问题

 

查询工资比WARD高的员工信息

第一:查询WARD的工资?

      select sal from emp where ename = 'WARD';

 

第二:查询工资比1250高的员工信息?

      select * from emp where sal > 1250;

 

子查询:

        select *

from emp

where sal > (

    select sal

    from emp

    where ename = 'WARD'

);

 

查询部门名为'SALES'的员工信息(方式一:子查询)

 

第一:查询部门名为'SALES'的编号?

      select deptno from dept where dname = 'SALES';

第二:查询部门号为30的员工信息?

      select * from emp where deptno = 30;

子查询:

      select *

      from emp

      where deptno = (

  select deptno

  from dept

  where dname = 'SALES'

      );

 

子查询细节:

1)子查询与父查询可以针对同一张表

2)子查询与父查询可以针对不同张表

3) 子查询与父查询在传统参数时,数量要相同

4) 子查询与父查询在传统参数时,类型要相同

5) 子查询与父查询在传统参数时,含义要相同

 

查询部门名为'SALES'的员工信息(方式二:多表查询)

select emp.*

from dept,emp

where (dept.deptno=emp.deptno) and (dept.dname='SALES');

 

查询每个员工编号,姓名,部门名,工资等级(三表查询,这三张表并无外健关联)

select e.empno,e.ename,d.dname,s.grade

from emp e,dept d,salgrade s

where (e.deptno=d.deptno) and (e.sal between s.losal and s.hisal);

 

查询工资最低的员工信息(单行子查询,使用=号)

第一:查询出工资最低是多少?

      select min(sal) from emp;

第二:查询工资为800的员工信息?

      select * from emp where sal = 800;

子查询:

      select *

      from emp

      where sal = (

select min(sal)

from emp

  );

 

查询部门名为'ACCOUNTING''SALES'的员工信息(多行子查询,使用in关键字)

第一:查询部门名为'ACCOUNTING''SALES'的部门编号?

      select deptno from dept where dname in ('ACCOUNTING','SALES');

第二:查询部门号为1030号的员工信息?

      select * from emp where deptno in (10,30);

子查询:

      select *

      from emp

      where deptno in (

   select deptno

   from dept

                   where dname in ('ACCOUNTING','SALES')

                   );

 

查询工资比20号部门【任意any】一个员工工资【低<】的员工信息(多行子查询,使用any关键字)

第一:查询20号部门的所有工资?

      select sal from emp where deptno = 20;

第二:查询工资比(800,2975,3000,1100,3000)任意一个低的员工信息?

      select * from emp where sal < any (800,2975,3000,1100,3000);   

oracle看来,<any就等于<集合中最大的那个值

子查询:

      select *

      from emp

      where sal <any (

select sal

from emp

where deptno = 20

      );

 

查询工资比30号部门【所有all】员工【低<】的员工信息(多行子查询,使用all关键字)

 

第一:查询出30部门所有员工的工资?    

      select sal from emp where deptno = 30;

第二:查询工资比(1600,1250,1250,2850,1500,950)中所有的工资都低的员工信息?

      select * from emp where sal <all (1600,1250,1250,2850,1500,950);

子查询:

      select *

      from emp

      where sal <all (

select sal

from emp

where deptno = 30

      );

 

注意:学员们,不容易理解的几个概念:

 

单行函数:输入一个参数,输出一个结果

多行函数:扫描多个参数,输出一个结果

 

单行子查询:子查询只会返回一个结果,例如:800,父查询用=/<>/>=/<=这些符号来比较

多行子查询:子查询会返回多于一个结果,例如:30,20,父查询用in/any/all这些符号来比较

 

当多表查询,子查询同时能解决问题时,按如下优先方案选择:

 

多表查询-->子查询

注意:上述结果不是说多表查询可以替代子查询,某些情况下,只能用子查询解决,例如:oracle分页

 

-------------------------------------------------------------------------------------集合查询

 

 

使用并集运算,查询20号部门或30号部门的员工信息

select * from emp where deptno = 20

union

select * from emp where deptno = 30;

注意:

union:二个集合中,如果都有相同的,取其一

union all:二个集合中,如果都有相同的,都取

 

使用set time/timing on,打开时间的开关

set time on;

set time off;

 

使用set tim/timing off,关闭时间的开关

set timing on;

set timint off;

 

使用交集运算[intersect],查询工资在1000-20001500-2500之间的员工信息(方式一)

select * from emp where sal between 1000 and 2000

intersect

select * from emp where sal between 1500 and 2500;

 

where行过滤,查询工资在1000-20001500-2500之间的员工信息(方式二)

select *

from emp

where (sal between 1000 and 2000) and (sal between 1500 and 2500);

 

使用差集运算[minus],查询工资在1000-2000,但不在1500-2500之间的员工信息(方式一)

select * from emp where sal between 1000 and 2000

minus

select * from emp where sal between 1500 and 2500;

 

使用where行过滤,查询工资在1000-2000,但不在1500-2500之间的员工信息(方式二)

select *

from emp

where (sal between 1000 and 2000) and (sal not between 1500 and 2500);

 

集合查询的细节:

1)集合操作时,必须确保集合列数是相等

select empno,ename,sal,comm from emp where deptno = 20

union

select empno,ename,sal from emp where deptno = 30;

 

2)集合操作时,必须确保集合列类型对应相同

select empno,ename,sal,comm from emp where deptno = 20

union

select empno,ename,sal,hiredate from emp where deptno = 30;

 

3A union B union C = C union B union A

select * from emp where deptno = 10

union

select * from emp where deptno = 20

union

select * from emp where deptno = 30;

 

4)当多个集合操作时,结果的列名由第一个集合列名决定

select empno "编号",ename "姓名",sal "薪水" from emp where deptno = 20

union

select empno,ename,sal from emp where deptno = 10;

 

当多表查询,子查询,集合查询都能完成同样任务时,按如下优化方案选择:

多表查询->子查询->集合查询

 

 

-------------------------------------------------------------------------------------oracle分页

 

 

回顾mysql分页

limit关键字

 

查询users表中前二条记录

select * from users limit 0,2

select * from users limit 2;

0表示第一条记录的索引号,索引号从0开始

2表示最多选取二个记录

 

查询出users前三条记录

select * from users limit 0,3

select * from users limit 3

 

查询出users2条到第4条记录

select * from users limit 1,3;

 

回顾hibernate分页API

Query.setFirstResult(0);

Query.setMaxResult(3);

什么是rownum,有何特点

1rownumoracle专用的关健字

2rownum与表在一起,表亡它亡,表在它在

3rownum在默认情况下,从表中是查不出来的

4)只有在select子句中,明确写出rownum才能显示出来

5rownumnumber类型,且唯一连续

6rownum最小值是1,最大值与你的记录条数相同

7rownum也能参与关系运算

   * rownum = 1    有值

   * rownum < 5    有值

   * rownum <=5    有值

   * rownum > 2    无值    

   * rownum >=2    无值

   * rownum <>2    有值  rownum < 2 相同

   * rownum = 2    无值

8)基于rownum的特性,我们通常rownum只用于<<=关系运算   

 

显示emp表中3-8条记录(方式一:使用集合减运算)

select rownum "伪列",emp.* from emp where rownum<=8

minus

select rownum,emp.* from emp where rownum<=2;

 

显示emp表中3-8条记录(方式二:使用子查询,在from子句中使用,重点)

select xx.*

from (select rownum ids,emp.* from emp where rownum<=8) xx

where ids>=2;

注意:在子查询中的别名,不可加""引号

 

显示emp表中5-9条记录

select yy.*

from (select rownum ids,emp.* from emp where rownum<=9) yy

where ids>=5;

注意:在项目中,from后台可能有真实表名,也可能用子查询看作的表名,

     同时真实表和子查询看作的表要做连接查询

 

 

-------------------------------------------------------------------------------------创建表和约束

 

 

回顾MySQL创建表语句users(id整型/name字符串/birthday日期型,默认今天)

drop table if exists users;

create table if not exists users(

   id int(5) auto_increment primary key,

   name varchar(4) not null,

   birthday date default '2015-4-27'

);

 

使用oracleSQL,创建用户表users(id整型/name字符串/birthday日期/sal整型,默认今天)

create table users(

  id number(5) primary key,

  name varchar2(8) not null unique,

  sal number(6,2) not null,

  birthday date default sysdate

);

 

进入回收站

drop table users;

 

查询回收站中的对象

show recyclebin;

 

闪回,即将回收站还原

flashback table 表名 to before drop;

flashback table 表名 to before drop rename to  新表名;

 

彻底删除users

drop table users purge;

 

清空回收站

purge recyclebin;

测试如下类型

1number(5)

insert into users(id,name,sal) values(1,'A',6666.66);     

insert into users(id,name,sal) values(11,'AA',6666.66);     

insert into users(id,name,sal) values(111,'AAA',6666.66);     

insert into users(id,name,sal) values(1111,'AAAA',6666.66);     

insert into users(id,name,sal) values(99999,'AAAAA',6666.66);     

insert into users(id,name,sal) values(100000,'AAAAAA',6666.66);

5表示最多存99999    

 

2number(6,2)

col sal for 9999.99

insert into users(id,name,sal) values(1,'A',6.66);     

insert into users(id,name,sal) values(11,'AA',66.666);     

insert into users(id,name,sal) values(111,'AAA',666.6666);     

insert into users(id,name,sal) values(1111,'AAAA',6666.66666);     

insert into users(id,name,sal) values(11111,'AAAAA',66666.666666);

number(6,2)

其中2表示最多显示2位小数,采用四舍五入,不足位数补0,同时要设置col ... for ...

其中6表示小数+整数不多于6

其中整数位数不得多于4位,可以等于4

 

3varchar2(8)

insert into users(id,name,sal) values(1,'A',7777.77);     

insert into users(id,name,sal) values(2,'AA',7777.77);     

insert into users(id,name,sal) values(3,'AAA',7777.77);     

insert into users(id,name,sal) values(4,'AAAA',7777.77);  

insert into users(id,name,sal) values(5,'AAAAA',7777.77);  

insert into users(id,name,sal) values(6,'AAAAAA',7777.77);  

insert into users(id,name,sal) values(7,'AAAAAAA',7777.77);  

insert into users(id,name,sal) values(8,'AAAAAAAA',7777.77);  

insert into users(id,name,sal) values(9,'AAAAAAAAA',7777.77);

  

insert into users(id,name,sal) values(1,'',7777.77);     

insert into users(id,name,sal) values(2,'哈哈',7777.77);     

insert into users(id,name,sal) values(3,'哈哈哈',7777.77);     

insert into users(id,name,sal) values(4,'哈哈哈哈',7777.77);  

insert into users(id,name,sal) values(5,'哈哈哈哈哈',7777.77);错  

 

8表示字节

GBK 2字节

 

4date:默认格式为:'27-4-15'

5CLOBCharacter Large OBject】:大文本对象,即超过65565字节的数据对象,最多存储4G

6BLOBBinary Large OBject】:大二进制对象,即图片,音频,视频,最多存储4G

 

emp表增加image列,alter table表名 add列名 类型(宽度)

alter table emp

add image blob;

 

修改ename列的长度为20个字节,alter table表名 modify列名 类型(宽度)

alter table emp

modify ename varchar2(20);

 

删除image列,alter table表名 drop column列名

alter table emp

drop column image;

 

重名列名enameusernamealter table表名 rename column原列名 to新列名

alter table emp

rename column ename to username;

 

emp表重命名empsrename原表名 to新表名

rename emp to emps;

 

注意:修改表时,不会影响表中原有的数据

 

笔试题:有【1000亿】条会员记录,如何用最高效的方式将薪水字段清零,其它字段内容不变?

 

第一:从emp表中删除sal字段

      alter table emp

      drop column sal;      

 

第二:向emp表中添加sal字段,且内容默认0

      alter table emp

      add sal number(6) default 0;

 

修改表不可回滚

 

创建表customers()orders(),使用primary key/not null/unique/default/foreign key约束

要体现【on delete cascade/on delete set null

需求:删除客户,级联删除他所有的订单

      delete from customers where id = 1;

需求:删除客户,不级联删除他所有的订单,只是将外健设置为NULL

      delete from customers where id = 1;

 

create table customers(

  id number(3) primary key,

  name varchar2(4) not null unique

);

insert into customers(id,name) values(1,'A');

insert into customers(id,name) values(2,'B');

 

create table orders(

  id number(3) primary key,

  isbn varchar2(6) not null unique,

  price number(3) not null,

  cid number(3),

  --constraint cid_FK foreign key(cid) references customers(id) on delete cascade

  constraint cid_FK foreign key(cid) references customers(id) on delete set null  

);

insert into orders(id,isbn,price,cid) values(1,'isbn10',10,1);

insert into orders(id,isbn,price,cid) values(2,'isbn20',20,1);

insert into orders(id,isbn,price,cid) values(3,'isbn30',30,2);

insert into orders(id,isbn,price,cid) values(4,'isbn40',40,2);

 

创建表students,包括id,name,gender,salary字段,使用check约束【性别只能是男或女,薪水介于60008000之间】

create table students(

  id number(3) primary key,

  name varchar2(4) not null unique,

  gender varchar2(2) not null check ( gender in ('','') ),

  salary number(6) not null check ( salary between 6000 and 8000 )

);

insert into students(id,name,gender,salary) values(1,'哈哈','',6000);

insert into students(id,name,gender,salary) values(2,'呵呵','',5000);

insert into students(id,name,gender,salary) values(3,'嘻嘻','',7000);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

培训要求

1)掌握增、删、改数据和事务操作

2)掌握【视图】和同义词

3)掌握【序列】和索引

4)了解有关用户和权限的控制

-------------------------------------------------------------------------------------准备篇

 

 

col empno for 9999;

col ename for a10;

col job for a10;

col mgr for 9999;

col hiredate for a12;

col sal for 9999;

col comm for 9999;

col deptno for 99;

col tname for a40;

set pagesize 80;

 

--创建新表xxx_emp,复制emp表中的结构,同时复制emp表的所有数据

create table xxx_emp

as

select * from emp;

 

 

-------------------------------------------------------------------------------------增删改数据

 

 

回顾SQL92/99标准的四大类

1DML(数据操纵语言):selectinsertupdatedelete

2DDL(数据定义语言):create tablealter tabledrop tabletruncate table

3DCL(数据控制语言):grant select any table to scott/revoke select any table from scott

4TCL(事务控制语言):commitrollbacksavepoint to 回滚点

 

emp表中插入一条记录(方式一:按表默认结构顺序)insert into表名 values ...语法

insert into emp values(1111,'JACK','IT',7788,sysdate,1000,100,40);

 

emp表中插入一条记录(方式二:按自定义顺序)insert into表名(列名) values ...语法

insert into emp(ENAME,EMPNO,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO)

values('MARRY',2222,'IT',7788,sysdate,1000,100,40);

 

emp表中插入NULL值(方式一:采用显示插入NULL值)

insert into emp values(3333,'SISI','IT',7788,sysdate,1000,NULL,40);

 

emp表中插入NULL(方式二:采用隐式插入NULL值),前提是所插入的字段允许插入NULL

insert into emp(ENAME,EMPNO,JOB,MGR,HIREDATE,SAL,DEPTNO)

values('SOSO',4444,'IT',7788,sysdate,1000,40);

 

使用&占位符,动态输入值,&可以运用在任何一个DML语句中,在values子句中使用,例如:'&ename'&sal

insert into emp values(&empno,'&ename','&job',&mgr,&hiredate,&sal,&comm,&xxxxxxxx);

注意:&sqlplus工具提供的占位符,如果是字符串或日期型要加''符,数值型无需加''

 

使用&占位符,动态输入值,&可以运用在任何一个DML语句中,在from子句中使用

select * from &table;

 

使用&占位符,动态输入值,&可以运用在任何一个DML语句中,在select子句中使用

select empno,ename,&colname from emp;

 

使用&占位符,动态输入值,&可以运用在任何一个DML语句中,在where子句中使用

select * from emp where sal > &money;

 

使用&占位符,动态输入值,&可以运用在任何一个DML语句中,在group by having子句中使用

select deptno,avg(sal)

from emp

group by &deptno

having avg(sal) > &money;

 

删除emp表中的所有记录

delete from emp;

 

xxx_emp表中所有20号部门的员工,复制到emp表中,批量插入,insert into 表名 select ...语法

insert into emp

select *

from xxx_emp

where deptno=20;

 

'SMITH'的工资增加20%

update emp set sal=sal*1.2 where ename = upper('smith');

 

'SMITH'的工资设置为20号部门的平均工资,这是一个条件未知的事物,优先考虑子查询

第一:20号部门的平均工资

      select avg(sal) from emp where deptno=20;

第二:将'SMITH'的工资设置为2207

      update emp set sal=2207 where ename = 'SMITH';

子查询:

     update emp

     set sal = (

select avg(sal)

        from emp

        where deptno=20

     )

     where ename = 'SMITH';   

 

删除工资比所有部门平均工资都低的员工,这是一个条件未知的事物,优先考虑子查询

第一:查询所有部门的平均工资

      select avg(sal) from emp group by deptno;

第二:删除工资比(*,*,*)都低的员工

      delete from emp where sal<all(*,*,*);

子查询:

      delete

      from emp

      where sal < all(

 select avg(sal)

         from emp

         group by deptno

      );

 

删除无佣金的员工

delete from emp where comm is null;

 

emp表丢入回收站,drop table表名

drop table emp;

 

从回收站将emp表闪回,flashback table表名 to before drop

flashback table emp tobefore drop;

 

查询回收站,show recyclebin

show recyclebin;

 

清空回收站,purge recyclebin

purge recyclebin;

 

使用关键字purge,彻底删除emp表,即不会将emp表丢入回收站,永久删除emp表,

drop table 表名 purge

drop table emp purge;

 

依据xxx_emp表结构,创建emp表的结构,但不会插入数据

create table emp

as

select * from xxx_emp where 1<>1;

 

创建emp表,复制xxx_emp表中的结构,同时复制xxx_emp表的所有数据

create table emp

as

select * from xxx_emp where 1=1;

注意:where不写的话,默认为true

 

emp截断,再自动创建emp表,truncate table表名

truncate table emp;

 

emp表,批量插入来自xxx_emp表中部门号为20的员工信息,只包括empnoenamejobsal字段

insert into emp(empno,ename,job,sal)

select empno,ename,job,sal

from xxx_emp

where deptno=20;

 

使用关键字purge,彻底删除emp表,即不会将emp表丢入回收站

drop table emp purge;

 

依据xxx_emp表,只创建emp表,但不复制数据,且emp表只包括empno,ename字段

create table emp(empno,ename)

as

select empno,ename from xxx_emp where 1=2;

 

emp表(只含有empnoename字段),批量插入xxx_emp表中部门号为20的员工信息

insert into emp(empno,ename)

select empno,ename from xxx_emp where deptno=20;

 

drop table truncate table delete from 区别:

drop table

1)属于DDL

2)不可回滚

3)不可带where

4)表内容和结构删除

5)删除速度快

 

truncate table

1)属于DDL

2)不可回滚

3)不可带where

4)表内容删除

5)删除速度快

 

delete from

1)属于DML

2)可回滚

3)可带where

4)表结构在,表内容要看where执行的情况

5)删除速度慢,需要逐行删除

软件工程师

 

 

-------------------------------------------------------------------------------------事务

 

回顾什么是事务?

一个不可分割的子操作形成一个整体,该整体要么全部执行成功,要么全部执行失败。例如:转帐

 

回顾为什么要用事务?

如果不用事务的话,为转帐为例,可能出现一个用户钱增加了,另一个用户钱不变

 

回顾编程中,事务可用于哪一层?

事务放在业务层

 

回顾jdbc编程中,如何使用事务?

connection.setAutoCommit(false);

pstmt.executeUpdate();

connection.commit();

connection.rollback();

 

回顾hibernate编程中,如何使用事务?

transaction.begin();

session.save(new User());

transaction.commit();

transaction.rollback();

 

回顾spring编程中,如何使用事务?

spring可以分为二种

>编程式事务,藕合

>声明式事务,解藕,提倡

 

Oracle的事务只针对DML操作,即select/insert/update/delete

 

回顾MySQL的事务开始:start transaction

Oracle的事务开始:第一条DML操作做为事务开始

 

Oracle的提交事务

1)显示提交:commit

2)隐藏提交:DDL/DCL/exit(sqlplus工具)

注意:提交是的从事务开始到事务提交中间的内容,提交到ORCL数据库中的DBF二进制文件

 

Oracle的回滚事务

1)显示回滚:rollback

2)隐藏回滚:关闭窗口(sqlplus工具),死机,掉电

注意:回滚到事务开始的地方

 

回顾什么是回滚点?

在操作之间设置的一个标志位,用于将来回滚之用

 

回顾为什么要设置回滚点?savepoint a;rollback to savepoint a;

如果没有设置回滚点的话,Oracle必须回滚到事务开始的地方,其间做的一个正确的操作也将撤销

 

使用savepoint 回滚点,设置回滚点a

savepoint a;

 

使用rollback to savepoint,回滚到回滚点a

rollback to savepoint a;

 

Oracle提交或回滚后,原来设置的回滚点还有效吗?

原回滚点无效了

 

Oracle之所以能回滚的原因是?

主要机制是实例池

 

回顾MySQL支持的四种事务隔离级别及能够解决的问题

1read uncommitted --不能解决任何缺点

2read committed   --脏读,Oracle默认

3reapatable read  --不可重复读,脏读,MySQL默认

4serializable     --幻读,不可重复读,脏读,效率低

 

注意:jdbc/dbutils速度快,但书写烦

      mybaits速度中等,但书写"中等"

      hibernate速度慢,但书写""

      

Oracle支持的二种事务隔离级别及能够解决的问题

Oracle支持:read committedserializable

 

Oracle中设置事务隔离级别为serializable

set transaction isolation level serializable;

 

演示二个用户同时操作emp表,删除KING这条记录,会有什么后果?

因为有隔离级别的存在,所以不会出现二个用户都删除了KING这条记录,

一定是一个用户删除KING成功,在该用户没有提交的情况下,另一个用户等待

 

 

-------------------------------------------------------------------------------------访问其它用户下的对象

 

 

声明:scotthr叫用户名/方案名/空间名

      scott--tiger

      hr-----lion

      

查询当前用户是谁

show user;

 

查询scott自己表空间下的所有对象时,可加,或不加用户名select * from emp;

select * from emp;

select * from scott.emp;

 

sysdba身份解锁hr普通帐户

alter user hr account unlock;

 

sysdba身份设置hr普通帐户的密码

alter user hr identified by lion;

 

scott查询hr表空间下的所有表时,必须得加用户名

select * from hr.jobs;

 

在默认情况下,每个用户只能查询自已空间下的对象的权限,不能查询其它用户空间下的对象

 

sysdba身份角色,授予scott用户查询所有用户空间下的对象权限

grant select any table to scott;

 

sysdba身份,撤销scott用户查询所有用户空间下的对象权限

revoke select any table from scott;

 

scott自已查看自己所拥有的权限

select * from user_sys_privs;

 

scott用户空间导航sysdba用户空间

conn / as sysdba;

 

sysdba用户空间导航到scott用户空间

conn scott/tiger;

 

scott用户空间导航到hr用户空间

conn hr/lion;

 

查询hr用户空间中的所有对象

select * from tab;

 

hr用户空间导航到scott用户空间

conn scott/tiger;

 

scott用户空间下,查询hr用户空间下的jobs表,必须加上hr用户空间名

select * from hr.jobs;

 

 

-------------------------------------------------------------------------------------视图

 

 

什么是视图【View

1)视图是一种虚表

2)视图建立在已有表的基础上,视图赖以建立的这些表称为基表

3)向视图提供数据内容的语句为SELECT 语句,可以将视图理解为存储起来的SELECT 语句

4)视图向用户提供基表数据的另一种表现形式

5)视图没有存储真正的数据,真正的数据还是存储在基表中

6)程序员虽然操作的是视图,但最终视图还会转成操作基表

7)一个基表可以有0个或多个视图

 

什么情况下会用到视图

1)如果你不想让用户看到所有数据(字段,记录),只想让用户看到某些的数据时,此时可以使用视图

2)当你需要减化SQL查询语句的编写时,可以使用视图,但不提高查询效率

 

视图应用领域

1)银行,电信,金属,证券军事等不便让用户知道所有数据的项目中

 

视图的作用

1)限制数据访问

2)简化复杂查询

3)提供数据的相互独立

4)同样的数据,可以有不同的显示方式

  

基于emp表所有列,创建视图emp_view_1create view视图名 as select对一张或多张基表的查询

create view emp_view_1

as

select * from emp;

 

默认情况下,普通用户无权创建视图,得让sysdba为你分配creare view的权限

 

sysdba身份,授权scott用户create view权限

grant create view to scott;

 

sysdba身份,撤销scott用户create view权限

revoke create view from scott;

 

基于emp表指定列,创建视图emp_view_2,该视图包含编号/姓名/工资/年薪/年收入(查询中使用列别名)

create view emp_view_2

as

select empno "编号",ename "姓名",sal "工资",sal*12 "年薪",sal*12+NVL(comm,0) "年收入"

from emp;

 

基于emp表指定列,创建视图emp_view_3(a,b,c,d,e),包含编号/姓名/工资/年薪/年收入(视图中使用列名)

create view emp_view_3(a,b,c,d,e)

as

select empno "编号",ename "姓名",sal "工资",sal*12 "年薪",sal*12+NVL(comm,0) "年收入"

from emp;

 

查询emp_view_3创建视图的结构

desc emp_view_3;

 

修改emp_view_3(id,name,salary,annual,income)视图,create or replace view视图名 as子查询

create or replace view emp_view_3(id,name,salary,annual,income)

as

select empno "编号",ename "姓名",sal "工资",sal*12 "年薪",sal*12+NVL(comm,0) "年收入"

from emp;

 

查询emp表,求出各部门的最低工资,最高工资,平均工资

select min(sal),max(sal),round(avg(sal),0),deptno

from emp

group by deptno;

 

创建视图emp_view_4,视图中包含各部门的最低工资,最高工资,平均工资

create or replace view emp_view_4

as

select deptno "部门号",min(sal) "最低工资",max(sal) "最高工资",round(avg(sal),0) "平均工资"

from emp

group by deptno;

 

创建视图emp_view_5,视图中包含员工编号,姓名,工资,部门名,工资等级

create or replace view emp_view_5

as

select e.empno "编号",e.ename "姓名",e.sal "工资",d.dname "部门名",s.grade "工资等级"

from emp e,dept d,salgrade s

where (e.deptno=d.deptno) and (e.sal between s.losal and s.hisal);

 

删除视图emp_view_1中的7788号员工的记录,使用delete操作,会影响基表吗

delete from emp_view_1 where empno=7788;写法正确,会影响基表

 

修改emp_view_1为只读视图【with read only】,再执行上述delete操作,还行吗?

create or replace view emp_view_1

as

select * from emp

with read only;

不能进行delete操作了

 

删除视图中的【某条】记录会影响基表吗?

会影响基表

 

将【整个】视图删除,会影响表吗?

不会影响基表

 

删除视图,会进入回收站吗?

不会进入回收站

 

删除基表会影响视图吗?

会影响视图

 

闪回基表后,视图有影响吗?

视图又可以正常工作了

 

 

-------------------------------------------------------------------------------------同义词

 

 

什么是同义词【Synonym

1)对一些比较长名字的对象(表,视图,索引,序列,。。。)做减化,用别名替代

 

同义词的作用

1)缩短对象名字的长度

2)方便访问其它用户的对象

 

创建与salgrade表对应的同义词,create synonym同义词 for表名/视图/其它对象

create synonym e for salgrade;

create synonym ev5 for emp_view_5;

 

sys身份授予scott普通用户create synonym权限

grant create synonym to scott;

 

sys身份从scott普通用户撤销create synonym权限

revoke create synonym from scott;

 

使用同义词操作salgrade

select * from s;

 

删除同义词

drop synonym ev5;

 

删除同义词,会影响基表吗?

不会影响基表

 

删除基表,会影响同义词吗?

会影响同义词

 

 

-------------------------------------------------------------------------------------序列

 

 

什么是序列【Sequence

1)类似于MySQL中的auto_increment自动增长机制,但Oracle中无auto_increment机制

2)是oracle提供的一个产生唯一数值型值的机制

3)通常用于表的主健值

4)序列只能保证唯一,不能保证连续

     声明:oracle中,只有rownum永远保持从1开始,且继续

5)序列值,可放于内存,取之较快

 

题问:为什么oracle不直接用rownum做主健呢?

rownum=1这条记录不能永远唯一表示SMITH这个用户

但主键=1确可以永远唯一表示SMITH这个用户

 

为什么要用序列

1)以前我们为主健设置值,需要人工设置值,容易出错

2)以前每张表的主健值,是独立的,不能共享

 

emp表的empno字段,创建序列emp_empno_seqcreate sequence 序列名

create sequence emp_empno_seq;

 

删除序列emp_empno_seqdrop sequence序列名

drop sequence emp_empno_seq;

 

查询emp_empno_seq序列的当前值currval和下一个值nextval,第一次使用序列时,必须选用:序列名.nextval

select emp_empno_seq.nextval from dual;

select emp_empno_seq.currval from dual;

 

使用序列,向emp表插入记录,empno字段使用序列值

insert into emp(empno) values(emp_empno_seq.nextval);

insert into emp(empno) values(emp_empno_seq.nextval);

insert into emp(empno) values(emp_empno_seq.nextval);

 

修改emp_empno_seq序列的increment by属性为20,默认start with1alter sequence序列名

alter sequence emp_empno_seq

increment by 20;

 

修改修改emp_empno_seq序列的的increment by属性为5

alter sequence emp_empno_seq

increment by 5;

 

修改emp_empno_seq序列的start with属性,行吗

alter sequence emp_empno_seq

start with 100;

 

有了序列后,还能为主健手工设置值吗?

insert into emp(empno) values(9999);

insert into emp(empno) values(7900);

 

删除表,会影响序列吗?

你无法做insert操作

 

删除序列,会影响表吗?

表真正亡,序列亡

 

hibernate中,如果是访问oracle数据库服务器,那么User.hbm.xml映射文件中关于<id>标签如何配置呢?

<id name="id" column="id">

   <generator class="increment/identity/uuid/sequence/native"/>

</id>

 

 

-------------------------------------------------------------------------------------索引

 

 

什么是索引【Index

1)是一种快速查询表中内容的机制,类似于新华字典的目录

2)运用在表中某个/些字段上,但存储时,独立于表之外

 

为什么要用索引

1)通过指针加速Oracle服务器的查询速度

2)通过rowid快速定位数据的方法,减少磁盘I/O

     rowidoracle中唯一确定每张表不同记录的唯一身份证

 

rowid的特点

1)位于每个表中,但表面上看不见,例如:desc emp是看不见的

2)只有在select中,显示写出rowid,方可看见

3)它与每个表绑定在一起,表亡,该表的rowid亡,二张表rownum可以相同,但rowid必须是唯一的

4rowid18位大小写加数字混杂体,唯一表代该条记录在DBF文件中的位置

5rowid可以参与=/like比较时,用''单引号将rowid的值包起来,且区分大小写

6rowid是联系表与DBF文件的桥梁

 

索引的特点

1)索引一旦建立, Oracle管理系统会对其进行自动维护,而且由Oracle管理系统决定何时使用索引

2)用户不用在查询语句中指定使用哪个索引

3)在定义primary keyunique约束后系统自动在相应的列上创建索引

4)用户也能按自己的需求,对指定单个字段或多个字段,添加索引

 

什么时候【要】创建索引

1)表经常进行 SELECT 操作

2)表很大(记录超多),记录内容分布范围很广

3)列名经常在 WHERE 子句或连接条件中出现

 注意:符合上述某一条要求,都可创建索引,创建索引是一个优化问题,同样也是一个策略问题

       

什么时候【不要】创建索引

1)表经常进行 INSERT/UPDATE/DELETE 操作

2)表很小(记录超少)

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

同上注意

 

emp表的empno单个字段,创建索引emp_empno_idx,叫单列索引,create index 索引名 on表名(字段,...)

create index emp_empno_idx

on emp(empno);

 

emp表的ename,job多个字段,创建索引emp_ename_job_idx,多列索引/联合索引

create index emp_ename_job

on emp(ename,job);

如果在where中只出现job不使用索引

如果在where中只出现ename使用索引

我们提倡同时出现enamejob

 

注意:索引创建后,只有查询表有关,和其它(insert/update/delete)无关,解决速度问题

 

删除emp_empno_idxemp_ename_job_idx索引,drop index索引名

drop index emp_empno_idx;

drop index emp_ename_job_idx;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

印象笔记>>

 

 

-------------------------------------------------------------------------------------java连接oracle的信息

 

 

Java访问Oracle服务器--orcl数据库---emp

 

private static String driver =

"oracle.jdbc.driver.OracleDriver";//访问oracle服务器的驱动名称

private static String url =

"jdbc:oracle:thin:@127.0.0.1:1521:orcl";//访问oracle服务器的连接字串

 

private static String username = "scott";//访问orcl数据库的用户名

private static String password = "tiger";//访问orcl数据库的密码

 

连接类型:在oracle中,用怎样的方式连接服务器,有二种方式连接oracle服务器,分别是thinoci

1)thin:通过oracle公司提供的jar

  连接简单,但速度相对慢

          将该目录下的E:\oracleDB\product\11.2.0\dbhome_1\jdbc\lib\ojdbc5.jar包导入到

          你项目的/WEB-INF/lib目录下

 

        2)oci:安装oracle公司提供的客户端安装程序,类似于QQ客户端,得事先安装

          连接复杂,但速度相对高

          且将该目录下的E:\oracleDB\product\11.2.0\dbhome_1\jdbc\lib\ojdbc5.jar包导入到

          你项目的/WEB-INF/lib目录下,与客户端一起使用,速度较快

 

        程序员使用thin方式即可     

   

 

 

 

 

 

 

 

 

培训要求

 

1)掌握PLSQL程序设计

 

2)掌握存储过程,函数和触发器

 

3)了解一些oralceSQL语句优化方案

 

 

-------------------------------------------------------------------------------------准备篇

 

 

col empno for 9999;

col ename for a10;

col job for a10;

col mgr for 9999;

col hiredate for a12;

col sal for 9999;

col comm for 9999;

col deptno for 99;

col tname for a40;

set pagesize 80;

 

 

-------------------------------------------------------------------------------------SQL对比PLSQL

 

 

SQL99是什么

1)是操作所有关系型数据库的规则

2)是第四代语言

3)是一种结构化查询语言

4)只需发出合法合理的命令,就有对应的结果显示

 

SQL的特点

1)交互性强,非过程化

2)数据库操纵能力强,只需发送命令,无需关注如何实现

3)多表操作时,自动导航简单,例如:

     select emp.empno,emp.sal,dept.dname

     from emp,dept

     where emp.deptno = dept.deptno

4)容易调试,错误提示,直接了当

5SQL强调结果

 

PLSQL是什么

     是专用于Oracle服务器,在SQL基础之上,添加了一些过程化控制语句,叫PLSQL

     过程化包括有:类型定义,判断,循环,游标,异常或例外处理。。。

     PLSQL强调过程

 

为什么要用PLSQL

     因为SQL是第四代命令式语言,无法显示处理过程化的业务,所以得用一个过程化程序设计语言来弥补SQL的不足之处,

     SQLPLSQL不是替代关系,是弥补关系

PLSQL程序的完整组成结构如下:

     [declare]

          变量声明;

     变量声明;

     begin

          DML/TCL操作;

  DML/TCL操作;

     [exception]

          例外处理;

  例外处理;

     end;

     /

注意:在PLSQL程序中,;号表示每条语句的结束,/表示整个PLSQL程序结束

 

书写PLSQL的工具有:

1SQLPLUS工具

2SQLDeveloper工具

3)第三方工具(PLSQL &其它)

 

PLSQLSQL执行有什么不同:

1SQL是单条执行的

2PLSQL是整体执行的,不能单条执行,整个PLSQL结束用/,其中每条语句结束用;号

 

 

------------------------------------------------------------------------------------PLSQL类型

 

 

写一个PLSQL程序,输出"hello world"字符串,语法:dbms_output.put_line('需要输出的字符串');

begin

    --SQLPLUS客户端工具输出字符串

    dbms_output.put_line('hello 你好');

end;

/

 

注意:

dbms_outputoracle中的一个输出对象

put_line是上述对象的一个方法,用于输出一个字符串自动换行

 

设置显示PLSQL程序的执行结果,默认情况下,不显示PLSQL程序的执行结果,语法:set serveroutput on/off;

set serveroutput on;

 

使用基本类型变量,常量和注释,求10+100的和

declare

    --定义变量

    mysum number(3) := 0;

    tip varchar2(10) := '结果是';

begin

    /*业务算法*/   

    mysum := 10 + 100;

    /*输出到控制器*/

    dbms_output.put_line(tip || mysum);

end;

/

 

输出7369号员工姓名和工资,格式如下:7369号员工的姓名是SMITH,薪水是800,语法:使用表名.字段%type

declare

    --定义二个变量,分别装姓名和工资

    pename emp.ename%type;

    psal   emp.sal%type;

begin  

    --SQL语句

    --select ename,sal from emp where empno = 7369;

    --PLSQL语句,将ename的值放入pename变量中,sal的值放入psal变量中    

    select ename,sal into pename,psal from emp where empno = 7369;

    --输出

    dbms_output.put_line('7369号员工的姓名是'||pename||',薪水是'||psal);    

end;

/

 

输出7788号员工姓名和工资,格式如下:7788号员工的姓名是SMITH,薪水是3000,语法:使用表名%rowtype

declare

    emp_record emp%rowtype;

begin

    select * into emp_record from emp where empno = 7788;

    dbms_output.put_line('7788号员工的姓名是'||emp_record.ename||',薪水是'||emp_record.sal);

end;

/

 

何时使用%type,何时使用%rowtype

当定义变量时,该变量的类型与表中某字段的类型相同时,可以使用%type

当定义变量时,该变量与整个表结构完全相同时,可以使用%rowtype,此时通过变量名.字段名,可以取值变量中对应的值

项目中,常用%type

 

 

------------------------------------------------------------------------------------PLSQL判断

 

 

使用if-else-end if显示今天星期几,是"工作日"还是"休息日"

declare

    pday varchar2(10);

begin

    select to_char(sysdate,'day') into pday from dual;

    dbms_output.put_line('今天是'||pday);

    if pday in ('星期六','星期日') then

dbms_output.put_line('休息日');

    else

dbms_output.put_line('工作日');

    end if;

end;

/

 

从键盘接收值,使用if-elsif-else-end if显示"age<16""age<30""age<60""age<80"

declare

    age number(3) := &age;

begin

    if age < 16 then

       dbms_output.put_line('你未成人');

    elsif age < 30 then

       dbms_output.put_line('你青年人');

    elsif age < 60 then

       dbms_output.put_line('你奋斗人');

    elsif age < 80 then

       dbms_output.put_line('你享受人');

    else

       dbms_output.put_line('未完再继');

    end if;

end;

/

 

 

-------------------------------------------------------------------------------------PLSQL循环

 

 

使用loop循环显示1-10

declare

    i number(2) := 1;

begin

    loop

        --i>10时,退出循环

        exit when i>10;

        --输出i的值

        dbms_output.put_line(i);

        --变量自加

        i := i + 1;  

    end loop;

end;

/

 

使用while循环显示1-10

declare

    i number(2) := 1;

begin

    while i<11

    loop

        dbms_output.put_line(i);

        i := i + 1;

    end loop;

end;

/

 

使用while循环,向emp表中插入999条记录

declare

    i number(4) := 1;

begin

    while( i < 1000 )

    loop

        insert into emp(empno,ename) values(i,'哈哈');

        i := i + 1;

    end loop;   

end;

/

 

使用while循环,从emp表中删除999条记录

declare

    i number(4) := 1;

begin

    while i<1000

    loop

        delete from emp where empno = i;

        i := i + 1;

    end loop;

end;

/

 

使用for循环显示20-30

declare

    i number(2) := 20;

begin

    for i in 20 .. 30

    loop

        dbms_output.put_line(i);

    end loop;

end;

/

 

 

-------------------------------------------------------------------------------------PLSQL游标

 

 

什么是光标/游标/cursor

类似于JDBC中的ResultSet对象的功能,从上向下依次获取每一记录的内容

 

使用无参光标cursor,查询所有员工的姓名和工资【如果需要遍历多条记录时,使用光标cursor,无记录找到使用cemp%notfound

declare

    --定义游标

    cursor cemp is select ename,sal from emp;

    --定义变量

    vename emp.ename%type;

    vsal   emp.sal%type;

begin

    --打开游标,这时游标位于第一条记录之前

    open cemp;

    --循环

    loop

       --向下移动游标一次

       fetch cemp into vename,vsal;

       --退出循环,当游标下移一次后,找不到记录时,则退出循环

       exit when cemp%notfound;

       --输出结果

       dbms_output.put_line(vename||'--------'||vsal);

    end loop;

    --关闭游标

    close cemp;

end;

/

 

使用带参光标cursor,查询10号部门的员工姓名和工资

declare

    cursor cemp(pdeptno emp.deptno%type) is select ename,sal from emp where deptno=pdeptno;

    pename emp.ename%type;

    psal emp.sal%type;

begin

    open cemp(&deptno);

    loop

        fetch cemp into pename,psal;  

        exit when cemp%notfound;

        dbms_output.put_line(pename||'的薪水是'||psal);

    end loop;

    close cemp;

end;

/

 

使用无参光标cursor,真正给员工涨工资,ANALYST1000MANAGER800,其它涨400,要求显示编号,姓名,职位,薪水

declare

    cursor cemp is select empno,ename,job,sal from emp;

    pempno emp.empno%type;

    pename emp.ename%type;

    pjob   emp.job%type;

    psal   emp.sal%type;

begin

    open cemp;

    loop

        fetch cemp into pempno,pename,pjob,psal;

        --循环退出条件一定要写

        exit when cemp%notfound;

        if pjob='ANALYST' then

            update emp set sal = sal + 1000 where empno = pempno;

        elsif pjob='MANAGER' then

            update emp set sal = sal + 800 where empno = pempno;

        else

    update emp set sal = sal + 400 where empno = pempno;

        end if;

    end loop;

    commit;

    close cemp;

end;

/

 

 

-------------------------------------------------------------------------------------PLSQL例外

 

 

使用oracle系统内置例外,演示除0例外【zero_divide

declare

    myresult number;

begin

    myresult := 1/0;

    dbms_output.put_line(myresult);

exception

    when zero_divide then

 dbms_output.put_line('除数不能为0');

 delete from emp;  

end;

/

 

使用oracle系统内置例外,查询100号部门的员工姓名,演示没有找到数据【no_data_found

declare

    pename varchar2(20);

begin

    select ename into pename from emp where deptno = 100;

    dbms_output.put_line(pename);

exception

    when NO_DATA_FOUND then

 dbms_output.put_line('查无该部门员工');

 insert into emp(empno,ename) values(1111,'ERROR');

end;

/

 

使用用户自定义例外,使用光标cursor,查询10/20/30/100号部门的员工姓名,演示没有找到数据【nohave_emp_found

 

 

------------------------------------------------------------------------------------存储过程概念

 

 

什么是存储过程【procedure】?

 

为什么要用存储过程?

    1PLSQL每次执行都要整体运行一遍,才有结果

    2PLSQL不能将其封装起来,长期保存在oracle服务器中

    3PLSQL不能被其它应用程序调用,例如:Java

 

存储过程与PLSQL是什么关系?

 

 

--------------------------------------------------------存储过程

 

 

创建无参存储过程hello,无返回值,语法:create or replace procedure过程名 as PLSQL程序

 

删除存储过程hello,语法:drop procedure过程名

 

调用存储过程方式一,exec 存储过程名

 

调用存储过程方式二,PLSQL程序

 

调用存储过程方式三,Java程序

 

创建有参存储过程raiseSalary(编号),为7369号员工涨10%的工资,演示in的用法,默认in,大小写不敏感

 

创建有参存储过程findEmpNameAndSalAndJob(编号),查询7788号员工的的姓名,职位,月薪,返回多个值,演示out的用法

 

什么情况下用exec调用,什么情况下用PLSQL调用存储过程?

 

用存储过程,写一个计算个人所得税的功能

 

 

-------------------------------------------------------------------------------------存储函数

 

 

创建无参存储函数getName,有返回值,语法:create or replace function函数名 return返回类型 as PLSQL程序段

 

删除存储函数getName,语法:drop function函数名

 

调用存储函数方式一,PLSQL程序

 

调用存储函数方式二,Java程序

 

创建有参存储函数findEmpIncome(编号),查询7369号员工的年收入,演示in的用法,默认in

 

创建有参存储函数findEmpNameAndJobAndSal(编号),查询7788号员工的的姓名(return),职位(out),月薪(out),返回多个值

 

 

-------------------------------------------------------------------------------------过程函数适合场景

 

 

声明:适合不是强行要你使用,只是优先考虑

 

什么情况下【适合使用】存储过程?什么情况下【适合使用】存储函数?

 

【适合使用】存储过程:

 

【适合使用】存储函数:

    

什么情况【适合使用】过程函数,什么情况【适合使用】SQL

 

【适合使用】过程函数:

    》需要长期保存在数据库中

            》需要被多个用户重复调用

            》业务逻辑相同,只是参数不一样

    》批操作大量数据,例如:批量插入很多数据

 

【适合使用】SQL

    》凡是上述反面,都可使用SQL

    》对表,视图,序列,索引,等这些还是要用SQL

 

                

-------------------------------------------------------------------------------------触发器

 

 

什么是触发器【Trigger】?

 

为什么要用触发器?

 

创建语句级触发器insertEmpTrigger,当对表【emp】进行增加【insert】操作前【before】,显示"hello world"

 

删除触发器insertEmpTrigger,语法:drop trigger触发器名

 

使用insert语句插入一条记录,引起insertEmpTrigger触发器工作

 

使用insert语句插入N条记录,引起insertEmpTrigger触发器工作

 

创建语句级触发器deleteEmpTrigger,当对表【emp】进行删除【delete】操作后【after】,显示"world hello"

 

使用delete语句删除一条记录,引起deleteEmpTrigger触发器工作

 

使用delete语句删除N条记录,引起deleteEmpTrigger触发器工作

 

星期一到星期五,且9-20点能向数据库emp表插入数据,否则使用函数抛出异常,

语法:raise_application_error('-20000','例外原因')

 

创建行级触发器checkSalaryTrigger,涨后工资这一列,确保大于涨前工资,语法:for each row/:new.sal/:old.sal

 

删除触发器,表还在吗?

 

将表丢到回收站,触发器还在吗?

 

当闪回表后,触发器会在吗?

 

彻底删除表,触发器会在吗?

 

 

-------------------------------------------------------------------------------------oracleSQL优化方案

 

 

为什么要Oracle优化:

       随着实际项目的启动,Oracle经过一段时间的运行,最初的Oracle设置,会与实际Oracle运行性能会有一些差异,这时我们       就需要做一个优化调整。

 

Oracle优化这个课题较大,可分为四大类:

       》主机性能

       》内存使用性能

       》网络传输性能

       SQL语句执行性能【程序员】

 

下面列出一些oracleSQL优化方案:

 

 

01)选择最有效率的表名顺序(笔试常考)

      ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,

      FROM子句中写在最后的表将被最先处理,

      FROM子句中包含多个表的情况下,你必须选择记录条数最少的表放在最后,

      如果有3个以上的表连接查询,那就需要选择那个被其他表所引用的表放在最后。

      例如:查询员工的编号,姓名,工资,工资等级,部门名

      select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname

      from salgrade,dept,emp

      where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)  

      1)如果三个表是完全无关系的话,将记录和列名最少的表,写在最后,然后依次类推

      2)如果三个表是有关系的话,将引用最多的表,放在最后,然后依次类推

 

 

02WHERE子句中的连接顺序(笔试常考)  

      ORACLE采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之左,

      那些可以过滤掉最大数量记录的条件必须写在WHERE子句的之右。  

      例如:查询员工的编号,姓名,工资,部门名  

      select emp.empno,emp.ename,emp.sal,dept.dname

      from emp,dept

      where (emp.deptno = dept.deptno) and (emp.sal > 1500)   

  

03SELECT子句中避免使用*

      ORACLE在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间

      select empno,ename from emp;

 

04)使用DECODE函数来减少处理时间

      使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表

 

05)整合简单,无关联的数据库访问

 

06)用TRUNCATE替代DELETE

   

07)尽量多使用COMMIT

      因为COMMIT会释放回滚点

 

08)用WHERE子句替换HAVING子句

      WHERE先执行,HAVING后执行

     

09)多使用内部函数提高SQL效率

     

10)使用表的别名

      salgrade s

     

11)使用列的别名

      ename e

 

12)用索引提高效率

      在查询中,善用索引

      

13)字符串型,能用=号,不用like

      因为=号表示精确比较,like表示模糊比较

 

14SQL语句用大写的

      因为Oracle服务器总是先将小写字母转成大写后,才执行

      eclipse中,先写小写字母,再通过ctrl+shift+X转大写;ctrl+shift+Y转小写

 

15)避免在索引列上使用NOT

      因为Oracle服务器遇到NOT后,他就会停止目前的工作,转而执行全表扫描

 

16)避免在索引列上使用计算

      WHERE子句中,如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描,这样会变得变慢

      例如,SAL列上有索引,

      低效:

      SELECT EMPNO,ENAME

      FROM EMP

      WHERE SAL*12 > 24000;

      高效:

      SELECT EMPNO,ENAME

      FROM EMP

      WHERE SAL > 24000/12;

 

17)用 >= 替代 >

      低效:

      SELECT * FROM EMP WHERE DEPTNO > 3   

      首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录

      高效:

      SELECT * FROM EMP WHERE DEPTNO >= 4  

      直接跳到第一个DEPT等于4的记录

 

18)用IN替代OR

      select * from emp where sal = 1500 or sal = 3000 or sal = 800;

      select * from emp where sal in (1500,3000,800);

 

19)总是使用索引的第一个列

      如果索引是建立在多个列上,只有在它的第一个列被WHERE子句引用时,优化器才会选择使用该索引

      当只引用索引的第二个列时,不引用索引的第一个列时,优化器使用了全表扫描而忽略了索引

      create index emp_sal_job_idex

      on emp(sal,job);

      ----------------------------------

      select *

      from emp  

      where job != 'SALES';       

 

20)避免改变索引列的类型,显示比隐式更安全

      当字符和数值比较时,ORACLE会优先转换数值类型到字符类型

      select 123 || '123' from dual;

      

    


 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值