您的位置:首页 > 数据库 > Oracle

20150902 --Oracle学习笔记

2015-09-02 20:16 295 查看
第二天

基本概念–数据库服务器、数据主和表的关系

所谓安装数据库服务器,只是在机器上装了一个数据库管理程序,这个管理程序可以管理多个数据库,一般开发人员会针对每个应用创建一个数据库。

为保存应用中实体的数据,一般会在数据库创建多个表,以保存程序中实体的数据。

数据库服务器、数据库和表的关系如图所示:

基本概念–数据在数据库中的存储方式

数据存在方式(主要是以表的形式)

表的管理–创建表(基本语句)

建表的基本语法:

create table table_name(

field1 datatype,

field1 datatype,

field1 datatype,



)

注:table_name表名;field指定列名(字段名);datatype指定列类型(字段数据类型)

注意:创建表时,要根据需保存的数据创建相应的列,并根据数据的类型定义相应的列类型。

例:user对象

id int

name string

password string

birthday date

快速入门示例:

SQL> create table users(

id number,

name varchar2(32),

password varchar2(32),

birthday date);

Id Name Password birthday

表的管理–oracle常用数据类型

分类 数据类型 说明

文本、二进制类型 char(size) char(20)

varchar(size) varchar(20)

nchar(n)

nvarchar2(n)

clob(character large object)

blob(binary large object) 定长 最大2000字符

变长 最大4000字符

Unicode数据类型,定长 最大2000字符

Unicode数据类型,变长 最大4000字符

字符型大对象,最大8TB

二进制数据 可以存放图片/声音 8TB

数值类型 number(p,s) p为整数位,s为小数位.范围:

1<=p<=38,-84<=s<=127

保存数据范围:

-1.0e-130<=number value<1.0e+126

保存在机器内部的范围:

1~22 bytes

时间日期 Date

TIMESTAMP(n)邮戳 包含年月日,时分秒。默认格式:DD-MON-YYYY。从公元前4712年1月1日到公元4712年12月31日的所有合法日期

n的取值为0-9,表示指定TIMESTAMP中秒的小数位数。N为可选。如果n为0,timestamp与date等价(不推荐)

number可以理解成是一个可变的数据类型,比如number(12),你放一个小整数,它占用的字节数就少,你放一个大整数,它占用的字节数就多。

oracle数据类型

1、char(size)存放字符串,它最大可以存放2000个字符,是定长。

举例说明:

create table test1(name char(32));//test1表中的name字段最多存放32个字符,不足32个字符oracle会用空格补齐,如果超过会报错。

2、varchar2(size)存放字符串,它最大可以存放4000个字符,是变长。

举例说明:

create table test2(name varchar2(16));//test2表中的name字段最多存放16个字符,实际有几个字符就占几个字符的空间,如果超过会报错。

特别说明:如果我们的数据的长度是固定的,比如商品编号(8位),则应当使用char来存放,因为这样存取的速度就会提高。如果存放的数据长度是变化的,则使用varchar2来存放。

3、nchar(n)以Unicode编码来存放字符串,它最大可以存放2000个字符,是定长。

举例说明:

create table test3(name nchar(32));//与char类似,只是以Unicode编码存放字符串

4、nvarchar(n)以Unicode编码来存放字符串,它最大可以存放4000个字符,是变长。

举例说明:

create table test4(name nvarchar2(16));//与varchar2类似,只是以Unicode编码存放字符串

特别说明:nchar和nvarchar2与char和varchar2的区别在于,nchar和nvarchar2不论存放英文字符或中文字符都只占1个字符。如存放a和存放’中’都只占1个字符位。而char和varchar2存放a占1个字符而存放’中’则占2个字符。

5、clob字符型大对象,它最大可以存放8TB,是变长。

与字符型的char/varchar2/nchar/nvarchar2的使用方式一样。

6、blob二进制数据,可存放图片、声音,它最大可以存放8TB,是变长。

与字符型的char/varchar2/nchar/nvarchar2的使用方式一样。

注意:一般情况下很少使用数据库来存放媒体类文件,一般只使用数据库来记录媒体类文件的URL地址。如果考虑到文件的安全性,可以存放到数据库中来保存。

7、number可以存放整数,也可存放小数,是变长。

number(p,s)//p代表整数位,s代表小数位

保存数据范围:-1.0e-130至1.0e+126;保存在机器内部的范围:1~22bytes

特别说明:

有效位:从左到右,第一个非0数就是第一个有效位。

s>0精确到小数点右边s位,并四舍五入。然后检验有效位是否<=p

s<0精确到小数点左边s位,并四舍五入。然后检验有效位是否<=p+|s|

s=0等价于number(p)此时number表示整数。

说明:-1.0e-130(科学计数法):就是-1.0乘以10的-130次方

1.0e+126:就是1.0乘以10的126次方

举例说明:

number(5,2)

表示一个小数有5位有效数,2位小数。范围-999.99~999.99

如果数值超出了位数限制就会被截取多余的位数。但在一行数据中的这个字段输入575.316,则真正保存到字段中的数值是575.32。

number(5)<=>number(5,0)

表示一个五位整数,范围-99999~99999。

输入57523.316,真正保存的数据是57523

oracle表的管理–oracle支持的数据类型

数值型(练习)

Actual Data Specified AS Stored As Actual Data Specified AS Stored As

123.89 NUMBER 123.89 123.2564 NUMBER 123.2567

123.89 NUMBER(3) 124 1234.9876 NUMBER(6,2) 1234.99

123.89 NUMBER(6,2) 123.89 12345.123456 NUMBER(6,2) Error

123.89 NUMBER(6,1) 123.9 1234.9876 NUMBER(6) 1235

123.89 NUMBER(4,2) Error 12345.345 NUMBER(5,-2) 12300

123.89 NUMBER(6,-2) 100 1234567 NUMBER(5,-2) 1234600

.01234 NUMBER(4,5) .01234 12345678 NUMBER(5,-2) Error

.00012 NUMBER(4,5) .00012 123456789 NUMBER(5,-4) 123460000

.000127 NUMBER(4,5) .00013 1234567890 NUMBER(5,-4) Error

.0000012 NUMBER(2,7) .0000012 12345.58 NUMBER(*,1) 12345.6

.00000123 NUMBER(2,7) .0000012 0.1 NUMBER(4,5) Error

1.2e-4 NUMBER(2,5) 0.00012 0.01234567 NUMBER(4,5) 0.01235

1.2e-5 NUMBER(2,5) 0.00001 0.09999 NUMBER(4,5) 0.09999

8、date,用于表示时间,(年/月/日/时/分/秒),是定长。

举例说明:

create table test5(birthday date);//添加时个要使用默认格式insert into test5 values(‘11-11月-11’);如使用insert into test5 values(‘2011-11-11’);则报错。

特别说明:oracle日期有默认格式为:DD-MON-YYYY,天-月-年;如果我们希望使用自己习惯的日期添加,也可以,但是需要借助oracle函数来添加。

oracle表的管理–创建表

建表–学生表

字段 字段类型

id 整型 number

name 字符型 varchar2

sex 字符型 char

brithday 日期型 date

fellowship 小数型 number(6,2)

resume 大文本型 clob

学生表

SQL>create table students(

id number,

name varchar2(64),

sex char(2),

brithday date,

fellowship number(10,2),

resume clob

);

班级表

SQL>create table class_(

class_id number,

class_name varchar2(32)

);

oracle表的管理–修改表

使用alter table语句添加、修改或删除列的语法

添加列基本语法:

alter table TABLENAME add(columnname datatype);

alter table 表名 add(列名(字段名) 列类型(字段类型));

修改列基本语法:

alter table TABLENAME modify(columnname datatype);

alter table 表名 modify(列名(字段名) 列类型(字段类型));

删除列基本语法:

删除多列语法:

alter table TABLENAME drop(columnname,columnname2,…);

alter table 表名 drop(列名(字段名),列名2(字段名2),…);

删除单列语法:

alter table TABLENAME drop column COLUMNNAME;

alter table 表名 drop column 列名(字段名);

修改表的名称基本语法:

rename OldTableName to NewTableName;

rename 表名 to 新表名;

修改列名基本语法:

alter table TABLENAME rename(OldColumnName to NewColumnName);

alter table 表名 rename(旧列名 to 新列名);

查看表结构基本语法:

desc TABLENAME;

desc 表名;

练习:

1、给学生表添加班级编号

SQL>alter table students add(class_id number);

2、学生姓名变成varchar2(30)

SQL>alter table students modify(name varchar2(30));

3、学生姓名变成char(30)

SQL>alter table students modify(name char(30));

4、删除学生表的fellowship字段

SQL>alter table students drop column fellowship;

SQL>alter table students drop(fellowship);

5、把学生表名students修改成stu

SQL>rename students to stu;

6、删除学生表

SQL>drop table stu;

oracle表的管理–添加数据

使用insert语句向表中插入数据

插入数据基本语法:

insert into table[(column [,column…])] values(value [,value…]);

insert into 表名[(列名 [,列名2…])] values(值 [,值2…]);

注意事项:

1、插入的数据应与字段的数据类型相同。

2、数据的大小应在列的规定范围内,例如:不能将一个长度为80的字符串加入到长度为40的列中。

3、在values中列出的数据位置必须与被加入的列的排列位置相对应。

4、字符和日期型数据应包含在单引号中。

5、插入空值,不指定或insert into table values(null);

6、给表的所有列添加数据时,可以不带列名直接添加values值。

向students添加数据

SQL>insert into students (id,name,sex,brithday,fellowship,resume) values(1,’张三’,’男’,’11

-11月-01’,23.34,’hello’);

SQL>insert into students values(2,’李四’,’男’,’11-11月-02’,67.34,’hello2’);

SQL>insert into students values(3,’王五’,’女’,’11-11月-03’,671.34,’hello3’);

插入部分字段与插入空值,语法是一样的。只是要注意,当字段设置可为空时,可以不用将字段列出。否则就需要将字段名和值添加进去。否则报错,具体参见上述插入数据6点注意事项。

insert into table[(column [,column…])] values(value [,value…]);

oracle表的管理–修改数据

使用update语句修改表中数据。

Update语句基本语法:

update tablename set columnname=expr1 [,columnname2=expr2,…][where where_definition];

update 表名 set 列名=表达式 [,列名2=表达式2,…][where 条件];

注意事项:

1、update语法可以用新值更新原有表行中的各列;

2、set子句指示要修改哪些列和要给予哪些值;

3、where子句指定应更新哪些行。如没有where子句,则更新所有的行。(特别小心)

对students中的数据进行修改

将张三的性别改成女

SQL>update students set sex=’女’ where name=’张三’;

把张三的奖学金改为10

SQL>update students set fellowship=10 where name=’张三’;

把所有人的奖金都指高10%

SQL>update students set fellowship=fellowship*1.1;

练习:

将所有学生奖学金修改为5000元

SQL>update students set fellowship=5000;

将姓名为’张三’的学生奖学金修改为3000元

SQL>update students set fellowship=3000 where name=’张三’;

将’李四’的奖学金在原有基础上增加1000元

SQL>update students set fellowship=fellowship+1000 where name=’李四’;

将没有奖学金同学的奖学金改成10元

SQL>update students set fellowship=10 where fellowship is null;

特别注意:当修改空记录时应用is null而不能使用=null或=”

oracle表的管理–删除数据

基本语法:

delete from TABLENAME [where where_definition];

delete from 表名 [where 条件表达式];

注意事项:

1、如果不使用where子句,将删除表中所有的数据。(特别注意)

2、delete语句不能删除某一列的值(可使用update)。

3、使用delete语句仅删除记录,不删除表本身。如要删除表,使用drop table语句。

4、同insert和update一样,从一个表中删除记录将引起其它表的参照完整性问题,在修改数据库数据时,头脑中应始终不要忘记这个潜在的问题。

删除的几种方法比较:

delete from 表名;

删除所有记录,表结构还在,写日志,可以恢复的,速度慢

drop table 表名;

删除表的结构和数据

delete from student where xh=’A001’;

删除一条记录

truncate table 表名;

删除表中的所有记录,表结构还在,不写日志,无法找回删除的记录,速度快。

设置保存点

savepoint 保存点名称;

回滚

rollback to 保存点名称;

特别注意:设置保存点及回滚操作是配合delete语句使用,用来找回使用delete删除的数据。而通过truncate删除的表数据是无法通过此方法找回的。

建议:

在使用delete删除表数据前使用savepoint设置保存点,防止数据误删除。

oracle表基本查询–介绍

在我们讲解的过程中我们利用scott用户存在的几张表(emp,dept,salgrade)为大家演示如何使用select语句,select语句在软件编程中非常的有用,希望大家好好的掌握。

基本select语句

基本语法:

select [distinct] *|{columnl,column2,column3..} from table [where {condition}];

select [是否剔除重复数据] *|{字段名(列名),字段名2(列名2),字段名3(列名3)..} from 表名 [where {条件}];注意事项:

1、select指定查询哪些列的数据;

2、column指定列名;

3、*代表查询所有列;

4、from指定查询哪张表;

5、distinct可选,指显示结果时,是否剔除重复数据;

6、where条件。

oracle表基本查询–简单的查询语句

查看表结构

SQL>desc 表名;

查询所有列

SQL>select * from 表名;

查询指定列

SQL>select 列1,列2,列3,.. from 表名;

如何取消重复行

SQL>select distinct deptno,job from emp;

查询SMITH的薪水,工作,所在部门

SQL>select sal,job,deptno from emp where ename=’SMITH’;

特别注意:oracle对sql语句不区分大小写,但对查询内容区分大小写。这与sqlserver是有区别的,sqlserver对查询内容不区分大小写。

使用算数表达式

显示每个雇员的年工资

SQL>select ename,sal*13+nvl(comm,0)*13 from emp;

使用列的别名

SQL>select ename “姓名”,sal*13+nvl(comm,0)*13 “年收入” from emp;

SQL>select ename 姓名,sal*13+nvl(comm,0)*13 年收入 from emp;

SQL>select ename as “姓名”,sal*13+nvl(comm,0)*13 as “年收入” from emp;

特别注意:oracle在使用别名时,可以用双引号或不使用或使用as来表明别名。但不能使用单引号。sqlserver是可以使用双引号、单引号。

如何处理null值

使用nvl函数来处理

nvl函数的使用,说明:nvl是oracle提供的函数,是用于处理null值使用的。sqlserver提供的则是isnull函数来处理null值。

SQL>select ename,sal*13+nvl(comm,0)*13 from emp;

nvl(值1,值2) 解释:nvl值1为null时则取值2,值1不为null时则取值1原值。

如何连接字符串(||)

SQL>select ename ||’年收入’||(sal*13+nvl(comm,0)*13) “雇员的年收入” from emp;

||在查询的时候,希望把多列内容做为一列内容返回可以使用||连接符。

面试题:

我们希望删除用户,同时保留该用户的数据对象,怎么处理?

1、oracle是锁定该用户。

SQL>alter user scott account lock;//锁定用户

2、这时用户已不能登录到数据库,但system用于依然可以使用它的数据对象。

3、解锁命令

SQL>alter user scott account unlock;//用户解锁

oracle表基本查询–简单的查询语句

使用where子句

如何显示工资高于3000的员工

SQL>select ename,sal from emp where sal>3000;

如何查找1982.1.1后入职的员工

SQL>select ename,hiredate from emp where hiredate>’1-1月-82’;

也可以使用to_char函数转换日期类型后再进行日期比较,如下:

SQL>select ename,hiredate from emp where to_char(hiredate,’yyyy-mm-dd’)>’1982-1-1’;

字符对比还是有一定出入的。不推荐使用。

如何显示工资在2000到2500的员工情况

SQL>select * from emp where sal>=2000 and sal<=2500;

SQL>select * from emp where sal between 2000 and 2500;

说明:between是指定区间内取值,如:between 2000 and 2500,取2000至2500内的值,同时包含2000和2500

如何使用like操作符

%:表示任意0到多个字符

_:表示任意单个字符

如何显示首字符为S的员工姓名和工资

SQL>select ename,sal from emp where ename like ‘S%’;

如何显示第三个字符为大写O的所有员工的姓名和工资

SQL>select ename,sal from emp where ename link ‘__O%’;

在where条件中使用in

如何显示empno为123,345,800…的雇员情况

SQL>select * from emp where empno=123 or empno=345 or emp=800;

SQL>select * from emp where empno in(123,345,800);

使用is null的操作符

如何显示没有上级的雇员的情况

SQL>select * from emp where mgr is null;

使用逻辑操作符号

查询工资高于500或是岗位为manager的雇员,同时还要满足他们的姓名首写字母为大写的J

SQL>select * from emp where (sal>500 or job=’MANAGER’) and (ename like ‘J%’);

使用order by子句

如何按照工资的从低到高的顺序显示雇员的信息

SQL>select * from emp order by sal asc;

注意:asc写或不写都是升序排序即从小到大排序,desc则是降序排序从大到小排序。

按照部门号升序而雇员的入职时间降序排列

SQL>select * from emp order by deptno,hiredate desc;

使用列的别名排序

SQL>select ename,sal*12 “年薪” from emp order by “年薪” asc;

别名需要使用“”号圈中。

oracle表复杂查询

在实际应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,现在我们给大家介绍较为复杂的select语句

数据分组-max,min,avg,sum,count(分组函数)

如何显示所有员工中最高工资和最低工资

SQL>select max(sal) “最高工资”,min(sal) “最低工资” from emp;

请查询最高年工资

SQL>select max(sal*13+nvl(comm,0)*13) “最高年工资”,min(sal*13+nvl(comm,0)*13) “最低年工资” from emp;

显示所有员工的平均工资和工资总和

SQL>select avg(sal) “平均工资”,sum(sal) “工资总和” from emp;

特别注意:avg(sal)不会把sal为null的行进行统计,因此我们要注意,如果,你希望为空值也考虑,则我们可以这样做

SQL>selec sum(sal)/count(*) from emp;

计算共有多少员工

SQL>select count(*) “共有员工” from emp;

扩展要求:

请显示工资最高的员工的名字,工作岗位

SQL>select ename,job from emp where sal=(select max(sal) from emp);

特别注意:select语句执行的顺序是从右向左执行,正好和书写的方式相反。

SQL>select ename,job from emp where sal=(select max(sal) from emp);

oracle会先执行select max(sal) from emp这个语句,得出最大工资后。再执行where条件前的语句。

请显示工资高于平均工资的员工信息

SQL>select * from emp where sal>(select avg(sal) from emp);

SQL>select * from emp where sal>(select sum(sal)/count(*) from emp);

oracle表复杂查询

group by和having子句

group by用于对查询的结果分组统计;(配合分组函数使用)

having子句用于限制(过滤)分组显示结果。(对分组后再使用)

如何显示每个部门的平均工资和最高工资

SQL>select avg(sal) “平均工资”,max(sal) “最高工资”,deptno “部门编号” from emp group by deptno;

显示每个部门的每种岗位的平均工资和最低工资

SQL>select avg(sal) “平均工资”,min(sal) “最低工资”,job “职位”,deptno “部门编号” from emp group by deptno,job order by deptno;

显示部门平均工资低于2000的部门号和它的平均工资

SQL>select avg(sal) “平均工资”,deptno “部门编号” from emp group by deptno having avg(sal)<2000;

对数据分组的总结:

1、分组函数(avg…)只能出现在选择列表、having、order by子句中;

2、如果在select语句中同时包含有group by/having/order by那么他们的顺序是group by/having/order by;

3、在选择列中如果有列、表达式和分组函数,那么这些列和表达式必需有一个出现在group by子句中,否则会出错。

如select deptno,avg(sal),max(sal) from emp group by deptno having avg(sal)<2000;

这里deptno就一定要出现在group by 中。

oracle表复杂查询–多表查询

说明:

多表查询是指基于两个和两个以上的表或是视图的查询,在实际应用中,查询单个表可能不能满足你的需求,(如显示sales部门位置和其员工的姓名),这种情况下需要使用到(dept表和emp表)

显示雇员名,雇员工资及所在的部门的名字[笛卡尔集]

规定:多表查询的条件是至少不能少于表的个数-1

注意:笛卡尔集,在多表查询的时候,如果不带任何条件,则会出现笛卡尔集,避免笛卡尔集多表查询的条件是,至少不能少于表的个数-1

SQL>select e.ename,e.sal,d.dname from emp e,dept d where d.deptno=e.deptno;

如何显示部门为10的部门名、员工名和工资

SQL>select d.dname,e.ename,e.sal,e.deptno from emp e,dept d where d.deptno=e.deptno and e.deptno=10;

显示各个员工的姓名、工资及其工资的级别

SQL>select e.ename,e.sal,s.grade from emp e,salgrade s where e.sal between s.losal and s.hisal;

注意:在多表查询时,不同的表中列名相同时要加表名,不同时可不加。(为增强可读性,建议都加表名或别名)

扩展要求:

显示雇员名,雇员工资及所在部门的名字,并按部门排序。

SQL>select e.ename,e.sal,d.dname from emp e,dept d where e.deptno=d.deptno order by d.dname;

oracle表复杂查询–多表查询

自连接

自连接是指在同一张表的连接查询

显示员工的上级领导的姓名

SQL>select e2.ename from emp e1,emp e2 where e1.mgr=e2.empno;

比如显示’FORD’的上级

SQL>select e1.ename “员工姓名”,e2.ename “领导姓名” from emp e1,emp e2 where e1.mgr=e2.empno and e1.ename=’FORD’;

扩展要求:

显示各员工的姓名和他的上级领导姓名

SQL>select e1.ename “员工姓名”,e2.ename “领导姓名” from emp e1,emp e2 where e1.mgr=e2.empno;

疑惑:这里我们看到king没有显示,因为king没有上级。如果我们希望把没有上级的员工也显示出来,则需要使用到外连接。外连接包括左外连接和右外连接。此处提到外连接,后面会详细讲解。

左外连接:select 列名,.. from 表名1 left join 表名2 on 条件;

SQL>select e1.ename “员工姓名”,e2.ename “直接上级领导” from emp e1 left join emp e2 on e1.mgr=e2.empno;

或者使用(+)在右边也可以实现左外连接。

SQL>select e1.ename “员工姓名”,e2.ename “领导姓名” from emp e1,emp e2 where e1.mgr=e2.empno(+);

右外连接:select 列名,.. from 表名1 right join 表名2 on 条件;

SQL>select e1.ename “员工姓名”,e2.ename “直接上级领导” from emp e2 right join emp e1 on e1.mgr=e2.empno;

或者使用(+)在左边也可以实现右外连接。

SQL>select e1.ename “员工姓名”,e2.ename “领导姓名” from emp e1,emp e2 where e2.empno(+)=e1.mgr;

左外连接和右外连接在这里提到,后面会详细讲解。

oracle表复杂查询–子查询

什么是子查询?

子查询是指嵌入在其它sql语句中的select语句,也叫嵌套查询。

单行子查询

单行子查询是指只返回一行数据的子查询语句。(说的是后面的条件是返回的是一行结果)

请思考:如果显示与smith同一部门的所有员工?

SQL>select * from emp where deptno=(select deptno from emp where ename=’SMITH’);

将SMITH排除在外不显示

SQL>select * from emp where deptno=(select deptno from emp where ename=’SMITH’) and ename<>’SMITH’;

SQL>select * from emp where deptno=(select deptno from emp where ename=’SMITH’) and ename!=’SMITH’;

多行子查询?

多行子查询指返回多行数据的子查询。(说的是后面的条件是返回的是多行结果)

请思考:如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号

SQL>select ename,job,sal,deptno from emp where job in (select distinct job from emp where deptno=10);

特别注意:多行子查询是不能使用=号的,=号是单行子查询(由于只返回一个结果所以使用=号),多行子查询返回的不是一个结果所以要使用in。

oracle表复杂查询–子查询

在多行子查询中使用all操作符

请思考:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

SQL>select ename,sal,deptno from emp where sal>all(select sal from emp where deptno=30);

扩展要求:大家想想还有没有别的查询方法?

SQL>select ename,sal,deptno from emp where sal>(select max(sal) from emp where deptno=30);

在多行子查询中使用any操作符(比其中任意一个员工工资高即可)

请思考:如何显示工资比部门30的任意一个员工的工资高的员工的姓名、工资和部门号

SQL>select ename,sal,deptno from emp where sal>any(select sal from emp where deptno=30);

扩展要求:大家想想还有没有别的查询方法?

SQL>select ename,sal,deptno from emp where sal>(select min(sal) from emp where deptno=30);

多列子查询(后面的条件是列)

单行子查询是指子查询只返回单列、单行数据,多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句。

请思考如何查询与smith的部门和岗位完全相同的所有雇员?

原始查询方法(不推荐)

多表多列查询:

SQL>select * from emp e,dept d where e.deptno=d.deptno and d.dname=(select d.dname from emp e,dept d where e.deptno=d.deptno and e.ename=’SMITH’) and e.job=(select job from emp where ename=’SMITH’);

单表多列查询:

SQL>select * from emp where deptno=(select deptno from emp where ename=’SMITH’) and job=(select job from emp where ename=’SMITH’);

多列查询(优化方法,在oracle下推荐使用)

SQL>select * from emp where (deptno,job)=(select deptno,job from emp where ename=’SMITH’);

特别注意:查询的列要与返回的列名相对应,顺序不能出错。否则报错。

练习题:

1、以下哪条语句是错误的?D

A、select empno,ename name,sal salary from emp;

B、select empno,ename name,sal as salary from emp;

C、select ename,sal*12 as “annual salary” from emp;

D、select ename,sal*12 annual salary from emp;

select ename,sal*12 “annual salary” from emp;

2、某用户希望显示补助非空的所有雇员信息,应该使用哪条语句?B

A、select ename,sal,comm from emp where comm<>null;

B、select ename,sal,comm from emp where comm is not null;

C、select ename,sal,comm from emp where comm<>0;

3、以下哪条语句是错误的?C

A、select ename,sal salary from emp order by sal;

B、select ename,sal salary from emp order by salary;

C、select ename,sal salary from emp order by 3;//order by支持数字排序,但不能越界。

注意:数字表示列select ename,sal salary from emp order by 2 表示按第二列升序

4、查看dept表和emp表的结构。

SQL>desc dept;

SQL>desc emp;

5、使用简单查询语句完成

(1)显示所有部门名称

SQL>select dname from dept;

(2)显示所有雇员名及其全年收入13月(工资+补助),并指定列名”年收入”。

SQL>select ename,sal*13+nvl(comm,0)*13 “年收入” from emp;

(3)显示存在雇员的所有部门号

SQL>select distinct deptno from emp where ename is not null;

6、限制查询数据

(1)显示工资超过2850的雇员姓名和工资

SQL>select ename,sal from emp where sal>2850;

(2)显示工资不在1500到2850之间的所有雇员名和工资

SQL>select ename,sal from emp where sal<1500 or sal>2850;

select ename,sal from emp where sal between 1500 and 2850;

(3)显示代码为7566的雇员姓名及所在部门代码

SQL>select ename,deptno from emp where empno=7566;

(4)显示部门10和30中工资超过1500的雇员名及工资

SQL>select ename,sal from emp where deptno in(10,30) and sal>1500;

SQL>select ename,sal from emp where (deptno=10 or deptno=30) and sal>1500;

(5)显示无管理者的雇员名及岗位

SQL>select ename,job from emp where mgr is null;

7、排序数据

(1)显示在1981年2月1日至1981年5月1日之间雇用的雇员名、岗位及雇佣日期,并以雇佣日期进行排序

SQL>select ename,job,hiredate from emp where hiredate between ‘1-2月-81’ and ‘1-5月-81’ order by hiredate;

SQL>select ename,job,hiredate from emp where to_char(hiredate,’yyyy-mm-dd’) between ‘1981-02-01’ and ‘1981-05-01’ order by hiredate;

(2)显示获得补助的所有雇员名、工资及补助,并以工资和补助降序排序。

select ename,sal,comm from emp where comm is not null order by sal desc,comm desc;

oracle表复杂查询–子查询

在from子句中使用子查询此知识点必需掌握

请思考:如何显示高于自己部门平均工资的员工的信息???

这里要用到数据查询的小技巧,把一个子查询当作一个临时表使用。

SQL>select e.ename,e.sal,t1.myavg,e.deptno from emp e,(select avg(sal) myavg,deptno from emp group by deptno) t1 where e.deptno=t1.deptno and e.sal>t1.myavg order by e.deptno;

下面方法不推荐使用(无法取出子查询(临时表)的值)

SQL>select e.* from emp e where e.sal>(select avg(sal) from emp where deptno=e.deptno);

注意: 分组函数一定要别名

在from子句中使用子查询

请思考:查找每个部门工资最高的人的详细资料

思路:得到所有的员工,进行筛选,每拿到一个员工,判断该员工的工资是否是他们部门的最高工资。

SQL>select e.*,t1.mysal from emp e,(select max(sal) mysal,deptno from emp group by deptno) t1 where e.deptno=t1.deptno and e.sal>=t1.mysal order by e.deptno;

SQL>select * from emp where sal in (select max(sal) from emp group by deptno) order by deptno;

SQL>select * from emp e where sal=(select max(sal) from emp where deptno=e.deptno) order by deptno;

在from子句中使用子查询

请思考:显示每个部门的信息(编号、名称)和人员数量???,我们一起完成。

SQL>select distinct d.deptno,d.dname,t1.myuser from dept d,(select deptno,count(*) myuser from emp group by deptno) t1 where d.deptno=t1.deptno(+) order by d.deptno;

SQL>select distinct d.deptno,d.dname,t1.myuser from dept d left join (select deptno,count(*) myuser from emp group by deptno) t1 on d.deptno=t1.deptno order by d.deptno;

在from子句中使用子查询

这里需要说明的当在from子句中使用子查询时,该子查询会被作为一个临时表来对待,当在from子句中使用子查询时,必需给予查询指定别名。

oracle表复杂查询–子查询

分页查询是我们学习任何一种数据库,必需掌握的一个要点。

mysql数据库的分页查询说明:

select * from 表名 where 条件 limit 从第几条取,取几条;

sqlserver数据库的分页查询说明:

select top 4 * from 表名 where id not in (select top 4 id from 表名 where 条件);

意思:排除前4条,再取4条记录。实际从第5条取到第8条。

详细说明:

select top 4 说明取4条记录;

select top 4 * from 表名 where 列名 not in (select top 4 列名 from 表名 where 条件);

红色的标注为关键字,必需有。

not in (select top 4 列名 from 表名 where 条件)这里top 4说明排除前4条数据,从第5条数据开始取值。

***oracle数据库的分页查询说明:

特别注意:oracle每张表都有rownum默认字段,默认情况下是不显示的。但是是一直存在的。

select emp.*, rownum from emp

select emp.*, rownum from emp where rowm between 3 and 7;(这样是不行的,因为Oracle认为这样效率很低)

SQL>select t2.* from (select t1.,rownum rn from (select from emp) t1 where rownum<=6) t2 where rn>=4;

解释:

select * from emp //为第一张表,查询表中的所有数据

select t1.* from (select emp.* ,rownum from emp) t1 where t1.rownum<10(错误)

select t1.,rownum rn from (select from emp) t1 where rownum<=6 //为第二张表,把表一查到的数据看成一张临时表从中取出前6条数据,并形成第二张临时表。

select t2.* from (select t1.,rownum rn from (select from emp) t1 where rownum<=6) t2 where rn>=4; //为第三张表,把表二中取到的6条数据看成临时表,并从这6条数据中从第4条取到第6条数据,再形成第三张临时表,也就是我们所要查询的最终结果。

分页查询语法模版:

select t2.* from (select t1.,rownum rn from (select from 表名) t1 where rownum<=大范围(取到多少条数据)) t2 where rn>=小范围(从第几条数据开始取);

特别说明:oracle分页查询是通过三层筛选法进行查询的。每一次都可以带where条件来对要查询的信息进行筛选。

建议:针对不同情况分页查询,尽可能的在最内层(第一层)设置条件,包括多表分页;第二层设置最大取值范围;第三层从第几条数据开始取值。

上面的这个sql分页查询模版是oracle数据库效率比较高的查询方法,在百万数据级别对数据进行查询都可以及时响应。

请思考:按照入职时间的先后顺序,查询从第7至第10个人是谁?

SQL>select t2.ename,t2.hiredate,t2.rn from (select t1.,rownum rn from (select from emp order by hiredate) t1 where rownum<=10) t2 where rn>=7;

看看分页查询的效率

模拟10万条数据的一个表:此方法用于对数据库进行测试使用。

以存在的表为模版,创建另一个表。

create table mytest as select empno,ename,sal,comm,deptno from emp;

自我复制(又称蠕虫复制)

insert into mytest (empno,ename,sal,comm,deptno) select empno,ename,sal,comm,deptno from mytest;

oracle的分页查询共三种方法

1、根据ROWID来分页(速率一般)

SQL>select * from emp where rowid in (select rid from (select rownum rn,rid from (select rowid rid,cid from emp order by cid desc) where rownum<10000) where rn>9980) order by cid desc;

看得更清楚点

select * from emp where rowid in

(select rid from

(select rownum rn,rid from

(select rowid rid,cid from emp order by cid desc)

where rownum<10000)

where rn>9980)

order by cid desc;

2、按分析函数来分页(速率慢)

SQL>select * from (select t.*,row_number() over(order by cid desc) rk from emp t) where rk<10000 and rk>9980;

3、按rownum来分页(推荐使用速率稳定且速率快)

SQL>select t2.* from (select t1.,rownum rn from (select from emp) t1 where rn<=10000) t2 where rn>=9980;

看得更清楚一点

select t2.* from

(select t1.*,rownum rn from

(select * from emp)

t1 where rn<=10000)

t2 where rn>=9980;

oracle表复杂查询–子查询

用查询结果创建新表

这个命令是一种快捷建表方法(主要用于数据库压力测试使用)

基本语法:

create table 新建表名 (列名1,列名2,列名3,..) as select 列名1,列名2,列名3,.. from 已有表名;

说明:

1、新建表名中的列名要与select中的列名一一对应,否则会报错;

2、as关键字不可少;

自我复制数据(蠕虫复制)

有时,为了对某个sql语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据。

基本语法:

insert into 表名 (列名1,列名2,列名3,..) select 列名1,列名2,列名3,.. from 表名;

说明:表名后的列名要与select后的列名一致,否则会报错。

oracle表复杂查询–合并查询

有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符union,union all,intersect,minus

1、union取并集

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。

select ename,sal,job from emp where sal>2500 union select ename,sal,job from emp where job=’MANAGER’;

解释:union并集,将多条查询结果进行合并,去除相同重复的查询结果。

2、union all取所有

该操作符与union相似,但是它不会取消重复行,而且不会排序。

select ename,sal,job from emp where sal>2500 union all select ename,sal,job from emp where job=’MANAGER’;

解释:union all的用法与union相似,但union all不会对多条查询结果进行合并、排序。只会将查询到的所有内容都显示出来,而不象union对查询结果进行合并过滤。

3、intersect取交集

使用该操作符用于取得两个结果集的交集。

select ename,sal,job from emp where sal>2500 intersect select ename,sal,job from emp where job=’MANAGER’;

解释:intersect是将多条查询结果,重复部分提取并显示出来。

4、minus取差集

使用该操作符用于取得两个结果集的差集,它只会显示存在第一个集合中,而不存在第二个集合中的数据。

select ename,sal,job from emp where sal>2500 minus select ename,sal,job from emp where job=’MANAGER’;

解释:minus取差集,是将前一条查询结果与第二条查询结果进行比较,去除满足条件2,所得到的结果。

oracle表内连接和外连接(重点)

概述:表连接分为内连接和外连接

内连接(inner join - on)

内连接实际上就是利用where子句对两张表形成的笛卡尔集进行筛选,我们前面学习的查询都是内连接,也是开发过程中用的最多的连接查询。

内连接基本语法:

select 列名1,.. from 表1 inner join 表2 on 条件;

说明:内连接只有两张表同时满足条件才会被查询到。

举例:显示员工的信息和部门名称

select e.*,d.dname from emp e,dept d where e.deptno=d.deptno;

等价于

select e.*,d.dname from emp e inner join dept d on e.deptno=d.deptno;

外连接

外连接分为三种:左外连接、右外连接、完全外连

1、 左外连接 (left join - on)(如果左侧的表完全显示我们就说是左外连接)

基本语法:

select 列名1,列名2,.. from 表1 left join 表2 on 条件;

或者

select列名1,列名2,.. from 表1,表2 where 条件1=条件2(+);

2、 右外连接 (right join - on)(如果右侧的表完全显示我们就说是右外连接)

基本语法:

select 列名1,列名2,.. from 表1 right join 表2 on 条件;

或者

select列名1,列名2,.. from 表1,表2 where 条件1(+)=条件2;

3、完全外连 (full outer join - on)(完全显示两个表,没有匹配的记录置为空)

基本语法:

select 列名1,列2,.. from 表1 full outer join 表2 on 条件;

创建两张表做测试使用stu/exam表

create table stu (id number,name varchar2(32));

insert into stu values(1,’jack’);

insert into stu values(2,’tom’);

insert into stu values(3,’kity’);

insert into stu values(4,’nono’);

create table exam (id number,grade number);

insert into exam values(1,56);

insert into exam values(2,76);

insert into exam values(11,8);

外连接

1、内连接案例(显示两表ID匹配的)

基本语法:select 字段1,字段2… 表名1 inner join 表名2 on 条件;

2、左连接(显示所有人的成绩,如果没有成绩,也要显示该人的姓名和id号,成绩显示为空)(右为显示空(左边全部显示)也要显示+写在右边)

SQL>select s.id,s.name,e.grade from stu s left join exam e on s.id=e.id;

SQL>select s.id,s.name,e.grade from stu s,exam e where s.id=e.id(+);

3、右外连接(显示所有成绩,如果没有名字匹配,显示空)(左边显示为空:(右边全部显示)也要显示+写在左边)

SQL>select s.id,s.name,e.grade from stu s right join exam e on s.id=e.id;

SQL>select s.id,s.name,e.grade from stu s,exam e where s.id(+)=e.id;

小结:实际上左外连接和右外连接是可以互为转换的。

4、完全外连接(显示所有成绩和所有人的名字,如果没有相应的匹配值,则显示空)

SQL>select s.id,s.name,e.grade from stu s full outer join exam e on s.id=e.id;

oracle表内连接和外连接

一个小练习

为加深大家对外连接的理解,我们做一个小练习

列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门。

SQL>select d.dname,e.* from dept d left join emp e on d.deptno=e.deptno;

SQL>select d.dname,e.* from dept d,emp e where d.deptno=e.deptno(+);

SQL>select d.dname,e.* from emp e right join dept d on d.deptno=e.deptno;

SQL>select d.dname,e.* from emp e,dept d where e.deptno(+)=d.deptno;

练习题3:

1、假定sales部门有10个雇员,其中9个雇员的工资为1000,另一个雇员的工资为null,那么使用avg函数取得该部门的平均工资时,结果应该是多少? A

A、1000 B、900

2、以下哪条语句是正确的?C

A、select deptno,sum(sal) from emp;

B、select deptno,avg(sal) from emp where avg(sal)>2000 group by deptno;

C、select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;

3、如果要显示所有的部门及其雇员信息,应该使用哪个语句?B

A、select a.dname,b.ename from dept a,emp b where a.deptno=b.deptno;

B、select a.dname,b.ename from dept a,emp b where a.deptno=b.deptno(+);

C、select a.dname,b.ename from dept a,emp b where a.deptno(+)=b.deptno;

4、以下哪条语句是不正确的?C

A、create table employee as select * from emp order by ename;

B、create view emp_vu as select * from emp order by ename;

C、select ename,job,sal from emp where job in(select job from emp where deptno=30 order by job);//对子查询排序无意义

5、以下哪个集合操作符不会执行排序操作?B

A、union B、union all C、intersect D、minus

6、使用分组函数和数据分组子句

(1)显示所有雇员的平均工资、总计工资、最高工资、最低工资。

SQL>select avg(sal),sum(sal),max(sal),min(sal) from emp;

(2)显示每种岗位的雇员总数、平均工资。

SQL>select count(*),avg(sal),job from emp group by job;

(3)显示雇员总数,以及获得补助的雇员数。

SQL>select count(*),count(comm) from emp;

(4)显示管理者的总人数

SQL>select count(distinct mgr) from emp;

(5)显示雇员工资的最大差额。

SQL>select max(sal)-min(sal) from emp;

(6)显示每个部门每个岗位的平均工资、每个部门的平均工资、每个岗位的平均工资。

SQL>select avg(sal),deptno,job from emp group by cube(deptno,job);

特别注意:cube立方体函数的使用,此函数用于分组统计。

7、使用连接查询完成

(1)显示部门20的部门名,以及该部门的所有雇员名、雇员工资及岗位

SQL>select e.deptno,d.dname,e.ename,e.sal,e.job from emp e,dept d where e.deptno=d.deptno and e.deptno=20;

(2)显示获得补助的所有雇员名、补助以及所在部门名

SQL>select e.ename,e.comm,d.dname from emp e,dept d where e.deptno=d.deptno and e.comm is not null;

(3)显示在dallas工作的所有雇员名、雇员工资及所在部门名

SQL>select e.ename,e.sal,d.dname from emp e,dept d where e.deptno=d.deptno and d.loc=’DALLAS’;

(4)显示雇员scott的管理者名称

SQL>select ename from emp where empno=(select mgr from emp where ename=’SCOTT’);

(5)查询emp表和salgrade表显示部门20的雇员名、工资及其工资级别

SQL>select e.ename,e.sal,s.grade from emp e,salgrade s where e.deptno=20 and e.sal between losal and hisal;

(6)显示部门10的所有雇员名、部门名以及其他部门名

SQL>select e.ename,d.dname from emp e right join dept d on e.deptno=d.deptno and e.deptno=10;

(7)显示部门10的所有雇员名、部门名以及其他雇员名

SQL>select e.ename,d.dname from emp e left join dept d on e.deptno=d.deptno and e.deptno=10;

(8)显示部门10的所有雇员名、部门名以及其他部门名和雇员名

SQL>select e.ename,d.dname from emp e full outer join dept d on e.deptno=d.deptno and e.deptno=10;

8、使用子查询完成

(1)显示blake同部门的所有雇员,但不显示blake

SQL>select * from emp where deptno=(select deptno from emp where ename=’BLAKE’) and ename!=’BLAKE’;

(2)显示超过平均工资的所有雇员名,工资及其部门号

SQL>select ename,sal,deptno from emp where sal>(select avg(sal) from emp);

(3)显示超过部门平均工资的所有雇员名、工资及部门号

SQL>select e.ename,e.sal,e.deptno,t1.mysal from emp e,(select avg(sal) mysal,deptno from emp group by deptno) t1 where e.deptno=t1.deptno and e.sal>t1.mysal order by e.deptno;

(4)显示高于clerk岗位所有雇员工资的所有雇员名、工资及岗位

SQL>select ename,sal,job from emp where sal>(select sum(sal) from emp where job=’CLERK’);

(5)显示工资、补助与scott完全一致的所有雇员名、工资及补助

SQL>select e.ename,e.sal,nvl(e.comm,0) ecomm,e.deptno from emp e,(select sal,nvl(comm,0) tcomm from emp where ename=’SCOTT’) t1 where e.sal=t1.sal and nvl(e.comm,0)=t1.tcomm;

注意:select t.empno f from emp t where empno>7369; (true)

select t.empno f from emp t where empno>7369; (true)

select t.empno “f” from emp t where empno>7369; (true)

select t.empno f from emp t where f>7369; (false)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: