Oracle数据库 基础

【学习目标】

1,能够理解Oracle数据库的基本概念

2,记忆Oracle DDL语句

3,掌握Oracle序列的使用

4,掌握oracle单行函数的使用

5,能够掌握oracle多行函数

6,学习并应用oracle分组统计

7,能够应用Oracle多表查询

8,掌握Oracle子查询

oracle介绍[了解]

ORACLE 数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S 体系结构的数据库之一。比如SilverStream 就是基于数据库的一种中间件。

ORACLE数据库是目前世界上使用最为广泛的数据库管理系统,作为一个通用的数据库系统,它具有完整的数据管理功能;作为一个关系数据库,它是一个完备关系的产品;作为分布式数据库它实现了分布式处理功能。但它的所有知识,只要在一种机型上学习了ORACLE知识,便能在各种类型的机器上使用它。

Oracle安装[了解]

  1. 导入虚拟电脑到virtualbox中,参考<<资料\01.xp系统已安装oracle10g的vb虚拟机\virtualBox导入虚拟机步骤.doc>>

  2. windows主机安装客户端连接虚拟机中oracle数据库,参考<<资料\03.oracle客户端连接工具PLSQL-Developer\主机安装PLSQL步骤并测试连接(xp虚拟机里面已安装,这个是主机安装步骤).doc>>

  3. 参考<<资料\05.中文乱码的测试及解决.doc>>,解决中文乱码问题

Oracle体系结构[理解]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-64nwee36-1582254021193)(media/4324369ce78b568a9a28fffa176eceb9.jpg)]

全局数据库(物理结构)

Oracle 数据库是数据的物理存储()。这就包括(数据文件ORA或者DBF、控制文件、联机日志、参数文件)。其实Oracle数据库的概念和其它数据库不一样,这里的数据库是一个操作系统只有一个库。可以看作是Oracle就只有一个大数据库。

mysql可以创建多个数据库,oracle一般只需要一个全局数据库(2G,以后所有数据都放在这里),可以创建多个(不建议)

全局数据库位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MS3uU0zj-1582254021194)(media/385737f81f3a7a29000f7b1bb11eccc1.png)]

用户

在mysql里面使用不同数据库,就是创建不同的数据库.但是在oracle想达到使用不同数据库怎么做呢?

答:

  • oracle数据的隔离是以用户为单位,oracle创建不同的用户等同于mysql创建不同的数据库,在mysql里面创建数据库为一个项目使用,但是以后在oracle里面创建用户为一个项目使用.

  • 多全局数据库,就会多个是实例服务.(oracle强烈不建议,有兼容性问题,导致整个数据库可能用不了.)

用户是在实例服务下建立的。不同实例可以建相同名字的用户。

表空间(逻辑结构)

表空间是Oracle 对物理数据库上相关数据文件(ORA 或者DBF文件)的逻辑映射。一个数据库在逻辑上被划分成一到若干个表空间,每个表空间包含了在逻辑上相关联的一组结构。每个数据库至少有一个表空间(称之为system
表空间)。

每个表空间由同一磁盘上的一个或多个文件组成,这些文件叫数据文件(datafile)。一个数据文件只能属于一个表空间。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdgxX9up-1582254021194)(media/025e21302d72dc92f819d43f3d4b7ed7.jpg)]

数据文件(dbf、ora物理结构)

数据文件是数据库的物理存储单位。数据库的数据是存储在表空间中的,真正是在某一个或者多个数据文件中。而一个表空间可以由一个或多个数据文件组成,一个数据文件只能属于一个表空间。一旦数据文件被加入到某个表空间后,就不能删除这个文件,如果要删除某个数据文件,只能删除其所属于的表空间才行。

注:
表的数据,是有用户放入某一个表空间的,而这个表空间会随机把这些表数据放到一个或者多个数据文件中

由于oracle 的数据库不是普通的概念,oracle是有用户和表空间对数据进行管理和存放的。但是表不是有表空间去查询的,而是由用户去查的。因为不同用户可以在同一个表空间建立同一个名字的表!这里区分就是用户了!

在这里插入图片描述

总结oracle体系结构

全局数据库

这里指物理磁盘上的数据库(物理结构,一个真实存在的磁盘目录),一般一台oracle服务器有1个全局数据库,文件占1G多。oracle允许一台电脑安装多个全局数据库,但是不建议这样做。因为一个全局数据库可以放所有的数据。

这里与mysql不一样,mysql是随意创建数据库。

用户

数据库用户用于连接到oracle并操作数据。mysql通过数据库为单位存储隔离数据,而oracle以用户为单位存储隔离数据。也就是oracle的用户相当于mysql里面一个个小数据库。java连接mysql需要指明连接的数据库名字,然而java连接oracle只需指明连接的用户

表空间

是一种逻辑结构(与物理结构相反,看不到摸不着)用于存储数据的空间,用户的数据存放在表空间上的,表空间的数据是在数据文件上的。

表空间可以在逻辑上给数据文件划分多个区域,每个区域是一个表空间。数据文件的数据是由多个表空间组成。

数据文件

是全局数据库里面一个数据文件(物理结构,一个真实存在的磁盘文件)。一个全局数据库包含N多个数据文件。 数据库实例服务

(也叫数据库实例),是一个服务进程,用于执行sql命令,将变化更新到数据文件上。

oracle系统服务介绍

xp虚拟机中服务列表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sD1mpADa-1582254021195)(media/4a5ad814e92023418141dcc46c5c1892.png)]

其中有2个服务是必须开启的,其他服务可以关闭

OracleServiceORCL,数据库实例服务,当前执行sql命令时用于操作磁盘物理数据库文件数据

OracleOraDb10g_home1TNSListener,监听服务,用于监听接收客户端发送的sql命令,并发送给数据库实例服务去执行.

使用客户端工具连接oracle常见问题

打开PL/SQL

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1xkvLJie-1582254021195)(media/3b997a95121564422ab12d53f8690315.png)]

点击oK登录,有时会出现如下效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-248CihFj-1582254021196)(media/ac22d424fc2f16f533cde0a99a68279e.png)]

需要到xp虚拟机中重启oracle实例服务

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nqBgrds4-1582254021196)(media/30a54b885ddd0367ab5d71d98aba1a7d.png)]

重新登录PL/SQL,登录成功后的效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ziRxObbb-1582254021196)(media/195f61f9ab2a7452b49249f0f09d5cdf.png)]

学习oracle的常用sql

操作sql命令的类型

DDL,数据定义语言,create/drop/alter,创建或销毁数据对象(表空间,用户,表)

DCL,数据控制语言,授权的,grant…等sql语句

DML,数据操纵语言,update/insert into/delete等sql语句

DQL,数据查询语言,select等sql语句(最难)

创建表空间[理解]

表空间是什么?

是ORACLE 数据库的逻辑单元。 数据库—表空间。一个表空间可以与多个数据文件(物理结构)关联。

一个数据库下可以建立多个表空间,一个表空间可以建立多个用户、一个用户下可以建立多个表。

create tablespace demotablespace 
	datafile 'c:\\db.dbf' 
	size 100m 
	autoextend on next 10m

demotablespace 为表空间名称

datafile 指定表空间对应的数据文件

size 后定义的是表空间的初始大小

autoextend on 自动增长 ,当表空间存储都占满时,自动增长

next 后指定的是一次自动增长的大小。

创建用户(DDL)

create user root identified by root default tablespace demotablespace 

identified by 后边是用户的密码

default tablespace 后边是表空间名称

oracle数据库与其它数据库产品的区别在于,表和其它的数据库对象都是存储在用户下的。

用户赋权限(DCL)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-14YatUXs-1582254021197)(media/d1bf491b30d9242ba8fd0bb78d7d390a.png)]

新创建的用户没有任何权限,登陆后会提示

Oracle 中已存在三个重要的角色:connect 角色,resource 角色,dba 角色。

CONNECT 角色

–是授予最终用户的典型权利,最基本的 权限有:

ALTER SESSION --修改会话

CREATE CLUSTER --建立聚簇

CREATE DATABASE LINK --建立数据库链接

CREATE SEQUENCE --建立序列

CREATE SESSION --建立会话

CREATE SYNONYM --建立同义词

CREATE VIEW --建立视图

RESOURCE 角色

–是授予开发人员的

CREATE CLUSTER --建立聚簇

CREATE PROCEDURE --建立过程

CREATE SEQUENCE --建立序列

CREATE TABLE --建表

CREATE TRIGGER --建立触发器

CREATE TYPE --建立类型

DBA 角色

–拥有全部特权,是系统最高权限,只有 DBA
才可以创建数据库结构,并且系统权限也需要DBA 授出,且DBA
用户可以操作全体用户的任意基表,包括删除

查看用户角色(connect,resource,dba)

SELECT * FROM USER_ROLE_PRIVS;

查看当前用户权限

select * from session_privs; 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7tKp6wRI-1582254021197)(media/Snipaste_2018-10-13_08-59-06.jpg)]

授予权限语法

格式1:grant 权限1,权限2 to 用户

格式2:grant 角色 to 用户 --推荐使用

grant dba to root

进入 system 用户下给用户赋予 dba 权限,否则无法正常登陆

Oracle数据类型[应用]

No数据类型描述
1varchar可变长度字符串, oracle不推荐使用,不确保任何版本的支持.所以就算代码写这个类型,oracle也会自动将其转换为varchar2
2varchar2(n)可变长度字符串,一个英文字符占一个字节,中文GBK占2个字节,中文utf-8占3个字节,oracle推荐使用,具有更好的版本兼容性。 字符长度<=4000字节。
3numberNUMBER(n)表示一个整数,长度是n,n有效范围1~38.NUMBER(m,n):表示一个小数,总长度是 m,小 数是n,整数是m-n。 N的有效范围,-84~127. 123.9876存入Number(5,2)结果为:123.99 12345.9876存入Number(5,-2)结果为:12300
4date表示日期类型
5Long可变长字符列,最大长度限制是2GB,用于不需要作字符串搜索的长串数据,如果要进行字符搜索就要用varchar2类型。 long是一种较老的数据类型,将来会逐渐被BLOB、CLOB等大的对象数据类型所取代
6CLOB大对象,表示大文本数据类型,可存 4G
7BLOB大对象,表示二进制数据,可存 4G,适合存储视频\文档等数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ndsolmyA-1582254021198)(media/6b4f6978b2d26e9309fc136de06db34c.png)]

表的管理[应用]

建表(DDL)

语法: create table 表名( 字段1 数据类型 [default默认值] 字段1 数据类型 [default默认值] … 字段n 数据类型 [default默认值] );

范例:创建person 表

create table person( pid number(10) primary key, name varchar2(200) not null, sex varchar2(2), birthday date );

插入测试数据

 insert into person(pid,name) values(1,'张三');
 
 insert into person values(2,'张三','男',to_date('2018-01-01','yyyy-MM-dd'));

因为oracle的事务机制,**对数据库行数据等变更处理(增、删、改)时,我们必须做提交事务才能让数据真正的插入到数据库中,**在同样在执行完数据库变更的操作后还可以把事务进行回滚,这样就不会插入到数据库。如果事务提交后则不可以再回滚。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qTKD5Uv9-1582254021198)(media\Snipaste_2018-10-13_09-14-28.jpg)]

提交:commit回滚:rollback

表删除

语法:DROP TABLE 表

1.完全销毁表(DDL)*

drop table person; 

2.删除表里面的数据(DML)

delete from person; 

表的修改

在 sql 中使用alter 可以修改表

  • 添加列语法:ALTER TABLE 表名称 ADD(列名 1 类型 [DEFAULT 默认值],列名 1 类型

[DEFAULT 默认值]…)

  • 修改列语法:ALTER TABLE 表名称 MODIFY(列名 1 类型 [DEFAULT 默认值],列名 1
    类型 [DEFAULT 默认值]…)

  • 修改列名: ALTER TABLE 表名称 RENAME column 列名 1 TO 列名 2

范例:在person 表中增加列address

增加列

alter table person add(address varchar2(10));

范例:把person 表的address 列的长度修改成 20 长度

修改列类型

alter table person modify(address varchar2(20));

范例:把person表字段address字段名称修改为address2

修改列名称

alter table person rename column address to address2;

数据库表数据的更新(DML)

INSERT(增加)

标准写法:

INSERT INTO 表名[(列名 1,列名 2,…)]VALUES(值 1,值 2,…)

简单写法(不建议)

INSERT INTO 表名 VALUES(值 1,值 2,…)

注意:使用简单的写法必须按照表中的字段的顺序来插入值,而且如果有为空的字段使用null

 insert into person values(3,'李四','男',to_date('2018-01-01','yyyy-MM-dd'),'');
序列

在很多数据库中都存在一个自动增长的列,如果现在要想在 oracle中完成自动增长的功能,则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。

语法: create sequence seqpersonid

CREATE SEQUENCE 序列名

[INCREMENT BY n][START WITH n]

[{MAXVALUE/ MINVALUE n|NOMAXVALUE}][{CYCLE|NOCYCLE}]

[{CACHE n|NOCACHE}];

注意:

maxvalue最大28个9, 9999999999999999999999999999,maxvalue不写默认就是maxvalue

NOMAXVALUE,也是有最大值的,27个9,

默认是NOCYCLE

范例:创建一个 seqpersonid 的序列,验证自动增长的操作 CREATE SEQUENCE seqpersonid;

Create sequence

-- Create sequence 
create sequence seqpersonid
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 5
cycle;

序列创建完成之后,所有的自动增长应该由用户自己处理,所以在序列中提供了以下的两种操作:

nextval :取得序列的下一个内容

select seqpersonid.nextval from dual;

执行上面语句一次,就会增加一次seqpersonid;

currval :取得序列的当前内容

select seqpersonid.currval from dual;

在插入数据时需要自增的主键中可以这样使用

在实际项目中每一张表会配一个序列,但是表和序列是没有必然的联系的,一个序列被哪一张表使用都可以,但是我们一般都是一张表用一个序列。

序列的管理一般使用工具来管理。

示例:使用序列插入自动增长的主键

insert into person values(seqpersonid.nextval,'李四 ',1,to_date('2018-8-18','yyyy-MM-dd'),'广州');

UPDATE(修改)

全部修改:UPDATE 表名 SET 列名 1=值 1,列名 2=值 2,…

局部修改:UPDATE 表名 SET 列名 1=值 1,列名 2=值 2,…WHERE 修改条件;

全部更新

-- 更新,全部更新
update person set address2 = '广州'

局部更新

-- 更新,局部更新
update person set address2 = '深圳' where pid = 2; 

DELETE(删除)

语法 : DELETE FROM 表名 WHERE 删除条件;

在删除语句中如果不指定删除条件的话就会删除所有的数据

delete from person where pid=4; 

修改scott用户密码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mA02ltvD-1582254021199)(media/bdc538cd55d23f8eb2679c92034237e6.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ba8DLd4t-1582254021199)(media/6396829f971357cb9d03d293d807fc5e.png)]

使用scott用户登录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XEexzApE-1582254021199)(media/caff8eb5db0b60f9ca7d405458a0f780.png)]

Scott用户下的表结构[了解]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1lJfUpf8-1582254021200)(media/4a0297f5a7e2022d242e71dc6a009ad8.png)]

在这里插入图片描述

SQL函数

单行函数[应用]

  1. 字符函数

接收字符输入返回字符或者数值,dual 是伪表

  1. 把小写的字符转换成大小的字符
 select upper('smith') from dual;

在这里插入图片描述

把大写字符变成小写字符

select lower('SMITH') from dual;
数值函数
  1. 四舍五入函数:ROUND()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yj6wY88T-1582254021203)(media/1269b1526762877a1cd25d729e201c0b.png)]

默认情况下ROUND 四舍五入取整,可以自己指定保留的位数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YPTGmaYi-1582254021203)(media/436d4f2482d4e359e885006232577e69.png)]

日期函数

Oracle中提供了很多和日期相关的函数,包括日期的加减,在日期加减时有一些规律

日期 – 数字 = 日期

日期 + 数字 = 日期

日期 – 日期 = 数字(单位:天)

1.范例:查询雇员进入公司的周数。

分析:查询雇员进入公司的天数(sysdate – 入职日期)/7 就是周数

在这里插入图片描述

2.获得两个时间段中的月数:**MONTHS_BETWEEN()**范例:查询所有雇员进入公司的月数

--日期函数 
--oracle系统关键字对象:sysdate,获取当前系统时间 
--操作日系如下: 
--日期-日期=数字(以天为单位) 
--日期+数字=日期 
--日期-数字=日期
select sysdate from dual; 
select sysdate+1 from dual; 
select sysdate-1 from dual; 

--oracle给字段起别名
select 'aaa' as "测试" from dual; 
select 'aaa' as 测试 from dual; 
select 'aaa' 测试 from dual;
select 'aaa' "测试" from dual;

--获取员工入职的天数,分析当前系统日期-入职日期
select emp.ename,emp.hiredate,sysdate-emp.hiredate 入职天数 from emp; 

--获取员工入职的周数,分析(当前系统日期-入职日期)/7
select emp.ename,emp.hiredate,(sysdate-emp.hiredate)/7 入职周数 from emp; 

--获取员工入职的月数 --months_between(日期1,日期2),就是日期1-日期2返回的相差的月数
select emp.ename,emp.hiredate,months_between(sysdate,emp.hiredate) 入职月数 from emp; 

--获取员工入职的年数 
--months_between(日期1,日期2)/12
select emp.ename,emp.hiredate,months_between(sysdate,emp.hiredate)/12 入职年数 from emp
转换函数

TO_CHAR:字符串转换函数

范例:查询所有的雇员将将年月日分开,此时可以使用TO_CHAR
函数来拆分拆分时需要使用通配符

年:y, 年是四位使用yyyy

月:m, 月是两位使用 mm

日:d, 日是两位使用dd

时:h,hh是12小时制,hh24是24小时制

分:mi,分钟两位mi

秒:s,秒是两位使用ss

在这里插入图片描述

2.在结果中 10 以下的月前面被补了前导零,可以使用fm去掉前导零

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4UCcIMlZ-1582254021204)(media/721cc2cb8ae3672f300c68efd3a03693.png)]

TO_DATE:日期转换函数

在这里插入图片描述

TO_DATE 可以把字符串的数据转换成日期类型

代码

|

--日期转换为字符串,to_char(日期,'格式')
--格式:yyyy-MM-dd HH:mi:ss,oracle不区分大小写
-- hh,12进制的小时
-- hh24,24进制的小时
--fmyyyy-MM-dd HH:mi:ss,去掉补0数据

select emp.hiredate from emp;--1980/12/17

select to_char(emp.hiredate,'yyyy-MM-dd') from emp;--1981-02-22

select to_char(emp.hiredate,'fmyyyy-MM-dd') from emp;--1981-2-22

select to_char(emp.hiredate,'yyyy-MM-dd HH:mi:ss') from emp;

--字符串转换为日期,to_date(字符串,'格式')
select to_date('2018-01-01','yyyy-mm-dd') from dual;

通用函数

  1. 空值处理nvl

范例:查询所有的雇员的年薪

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E47z9Jdf-1582254021204)(media/970556a899f3df702245d300c4d1113b.jpg)]

我们发现很多员工的年薪是空的,原因是很多员工的奖金是 null,null
和任何数值计算都是

null,这时我们可以使用nvl 来处理。

在这里插入图片描述

Decode 函数
--if-else判断函数decode函数,格式:
-- decode(数据,'aa','数据为aa的时候返回的值','bb','数据为bb的时候返回的值',...,'else之前条件都不符合返回的值')
-- 显示员工职位中文名字
select emp.ename,
       emp.job, 
       decode(emp.job,
              'CLERK','业务员',
              'SALESMAN','销售员',
              'MANAGER','经理',
              /*'ANALYST','分析师',*/
              'PRESIDENT','总裁',
              '其他'
       ) 中文职位
  from emp;

在这里插入图片描述

范例:查询出所有雇员的职位的中文名

case when函数

语法:

CASE expr

WHEN comparison_expr1 THEN return_expr1

[WHEN comparison_expr2 THEN return_expr2

WHEN comparison_exprn THEN return_exprn

ELSE else_expr]

END

范例

Select emp.empno,
        emp.ename,
        case emp.job 
             when 'CLERK' then '业务员'
             when 'SALESMAN' then '销售'
             when 'MANAGER' then '经理'
             when 'ANALYST' then '分析员'
             when 'PRESIDENT' then '总裁'
             else '无业'
        end 职位 from emp;

效果

在这里插入图片描述

多行函数(聚合函数)

  1. 统计记录数count()

范例:查询出所有员工记录数

 --所有员工记录数 
 select count(*) from emp; 

效果

在这里插入图片描述

min()函数

范例:查询出来员工最低工资

在这里插入图片描述

max()函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gluQDKUl-1582254021206)(media/bd5591a9ffa438b85819be26785f350d.png)]

范例:查询出员工的最高工资

avg()函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nEAefboT-1582254021206)(media/2c92b661810e5e12d7f2696a24c0669d.png)]

范例:查询出员工的平均工资

  1. 求和函数 sum()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x7jNoBh3-1582254021206)(media/aed737ea0d0b255641b2c35861a180c6.png)]

范例:查询出 20 号部门的员工的工资总和

分组统计

分组统计需要使用 GROUP BY 来分组

语法:SELECT * |列名 FROM 表名 {WEHRE 查询条件} {GROUP BY 分组字段}
ORDER BY 列名 1 ASC|DESC,列名 2…ASC|DESC

范例:查询出每个部门的平均工资

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cOvE0go2-1582254021206)(media/9862177479a61032dc198faddcd6fb17.png)]

范例:查询每个部门的人数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ztiBHAo-1582254021206)(media/fa5873b04235f02b42b6a831fe7e19d0.png)]

如果我们想查询出来部门编号,和部门下的人数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKcBSBoe-1582254021207)(media/826b49bc4323547c80f132442b22b047.png)]

我们发现报了一个 ORA-00937 的错误

注意:

  1. 如果使用分组函数,SQL 只可以把 GOURP BY分组条件字段和分组函数查询出来,不能有其他字段。

  2. 如果使用分组函数,不使用 GROUP BY 只可以查询出来分组函数的值

错误效果如下:查询字段没有在分组条件字段里面,导致查询报错

在这里插入图片描述

范例:按部门分组,查询出部门名称和部门的员工数量

范例:查询出部门人数大于 5 人的部门

在这里插入图片描述

分析:需要给 count(ename)加条件,此时在本查询中不能使用 where,可以使用HAVING

范例:查询出部门平均工资大于 2000 的部门

在这里插入图片描述

多表查询[应用]

内连接

:多表连接基本查询

使用一张以上的表做查询就是多表查询

语法: SELECT {DISTINCT} *|列名… FROM 表名 别名,表名 1 别名

{WHERE 限制条件 ORDER BY 排序字段 ASC|DESC…}

范例:查询员工表和部门表

在这里插入图片描述

我们发现产生的记录数是 56 条,我们还会发现emp 表是 14 条,dept 表是 4 条,56
正是emp

表和dept表的记录数的乘积,我们称其为笛卡尔积。

如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。

在两张表中我们发现有一个共同的字段是 depno,depno就是两张表的关联的字段,我们可以使用这个字段来做限制条件,两张表的关联查询字段一般是其中一张表的主键,另一张表的外键。

在这里插入图片描述

关联之后我们发现数据条数是 14 条,不在是 56条。多表查询我们可以为每一张表起一个别名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WbPf5ukq-1582254021209)(media/74a07a3ae5908e44ab80f1cf9bf96843.png)]

范例:查询出雇员的编号,姓名,部门的编号和名称,地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r8CDP2NP-1582254021209)(media/1d2af15848c24f4cfeeb7e219661c2fd.png)]

范例:查询出每个员工的上级领导

分析:emp 表中的 mgr 字段是当前雇员的上级领导的编号,所以该字段对 emp表产生了自身关联,可以使用 mgr 字段和empno 来关联

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PSRKe0Ok-1582254021209)(media/882bcceab29b0dc92ada8428a1d6b81b.png)]

范例:在上一个例子的基础上查询该员工的部门名称

分析:只要在上一个例子基础上再加一张表的关联,使用 deptno 来做关联字段即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pFRW91Np-1582254021209)(media/b115805acbe1da33b2be254296faa4a1.png)]

范例:在上一个例子的基础上查询出每个员工 工资等级和他的上级领导工资等级

select e1.empno, e1.ename, e1.deptno, e1.sal,d1.dname,s1.grade 员工工资级别, e2.empno, e2.ename, e2.sal,s2.grade 领导工资级别
  from emp e1, emp e2,dept d1,salgrade s1,salgrade s2
 where e1.mgr = e2.empno 
   and e1.deptno=d1.deptno
   and e1.sal between s1.losal and s1.hisal
   and e2.sal between s2.losal and s2.hisal;

运行效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3THjPaf-1582254021210)(media/58357742ca4e9c6a39e2ed32d9190bfe.png)]

外连接(左右连接)

–外连接

– 左外连接(左连接)

– 右外连接(右连接)

–上面查询出13条数据,员工表14条数据,因为总裁没有上级领导所以总裁没有出来

–范例:查询出所有员工的上级领导(所有员工,就是14条数据全部显示出来)

-- 标准的左连接
select e1.empno, e1.ename, e1.deptno, e1.sal, e2.empno, e2.ename, e2.sal
  from emp e1 left join  emp e2 on e1.mgr = e2.empno;
-- oracle独有方式
--全量表,那个数据全出来,没有出来需要拉出来,使用(+)
select e1.empno, e1.ename, e1.deptno, e1.sal, e2.empno, e2.ename, e2.sal
  from emp e1, emp e2
 where e1.mgr = e2.empno(+);

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nxmZ8UTy-1582254021210)(media/73daec6fbcb150d38e98c0fdb8a26a22.png)]

–范例:查询出所有的部门下的员工,要求把没有员工的部门也展示出来

select * from dept,emp 
where dept.deptno=emp.deptno(+)

效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zLEBmSNA-1582254021210)(media/8bbdbf38473e855157c1bf0333354ddc.png)]

子查询[应用]

--9.子查询
--查询比SCOTT工资高的员工
select * from emp where sal>(select sal from emp where ename='SCOTT')

--查询工资最低的员工
select * from emp where sal=(select min(sal) from emp)

--查询出和scott同部门并且同职位的员工
select * from emp 
where deptno=(select deptno from emp where ename='SCOTT')
  and  job=(select job from emp where ename='SCOTT')
  and ename != 'SCOTT'
  
--不等于2个格式!=或<>
--优化
select * from emp 
where (deptno,job)=(select deptno,job from emp where ename='SCOTT')
  and ename <> 'SCOTT'

--查询每个部门的最低工资和最低工资的员工和部门名称

select e.empno, e.ename, e.sal, e.deptno, d.dname
  from (select deptno, min(sal) minSal from emp group by deptno) t1,
       emp e,
       dept d
 where t1.minSal = e.sal
   and t1.deptno = e.deptno
   and e.deptno = d.deptno
   
--总结:能用子查询就不要用表连接,因为子查询比表连接快
--查询20号部门的员工名称,部门名称
select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno and e.deptno=20  
--笛卡尔积56次,过滤部门号20次
select e.ename,(select dname from dept where deptno=20) from (select * from emp where deptno=20) e 
--只有过滤部门编号20次

Rownum与分页查询[应用]

ROWNUM:表示行号,实际上此是一个列,但是这个列是一个伪列,此列可以在每张表中出现。范例:查询emp
表带有 rownum 列。

注意:

1、与rownum同一级的*号不能单独出现,必须结合相关的表格;

2、将rownum转换为子查询的一列,之后就可以使用大于号;

3、先使用子查询排序,再加动态序号列,最后分页;

select rownum, t.* from emp t

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h28KORqn-1582254021210)(media/5ae73a922d52ffd231f66b9fd3ba924c.png)]

我们可以根据 rownum 来取结果集的前几行,比如前 5 行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s0VCG8Sf-1582254021210)(media/f076730cea5b1df4351bf76d092cab94.png)]

----------分页
--mysql使用limit分页,oracle使用rownum
--rownum,伪列,不是真实的一列,是动态给查询结果每行加一个序号
select emp.*,rownum from emp;

--员工数据分页查询,每页显示5条,查询第一页、第二页数据
--第一页
select emp.*,rownum from emp where rownum < 6;
--第二页
select emp.*,rownum from emp where rownum < 11 and rownum >5;--查询不到,rownum不可以使用大于号
--将rownum转换为子查询的一列,之后就可以使用大于号
select * from (
	select emp.*,rownum rowno from emp) t1
    where t1.rowno<11 
    and t1.rowno>5
    
--按照工资由高到低查询
--第一页
select emp.*,rownum from emp  order by emp.sal desc; --序号不对了,因为先查询,后排序

--先使用子查询排序,再加动态序号列,最后分页
select *
  from (select t1.*, rownum rowno
          from (select emp.* from emp order by emp.sal desc) t1) t2
 where t2.rowno < 6; 
--第二页
select *
  from (select t1.*, rownum rowno
          from (select emp.* from emp order by emp.sal desc) t1) t2
 where t2.rowno < 11
   and t2.rowno > 5;

总结:通用分页sql

select * from (
select emp.*,rownum num from emp) t1 where t1.num>? and  t1.num<?

num1 =(curPage-1)*pageSize
num2 =curPage*PageSize+1;
  • 28
    点赞
  • 212
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值