Oracle数据库
笔记基于视频教程:黑马程序员 Oracle 数据库精讲,从 0 到 1 学会 Oracle 数据库
一、Oracle 数据库相关概念
-
数据库
在 MySQL 中,我们可以创建许多个数据库,而在 Oracle 中,我们只能在安装的时候创建一个数据库。 -
实例
在使用 Oracle 数据库的时候,如果我们需要一台机器上用多个库怎么办,是不是需要安装多个 Oracle 数据库?Oracle 数据库为了解决这个问题,引入了实例的概念,每个实例就是一个数据库,他们之间互不干扰,类似于 java 的类与对象的关系,我们写代码的使用只用定义一个类,但是可以创建这个类的多个对象。 -
数据文件(dbf)
数据文件就是 Oracle 数据库存储数据的文件。 -
表空间
表空间是 Oracle 对数据文件的逻辑映射。一个数据库在逻辑上被划分成一个到多个表空间。每个数据库至少有一个表空间。每个表空间由同一磁盘上的一个或多个文件组成。具体结构如下图:
-
用户
用户是在表空间下建立的,用户登录后只能看到和操作自己的表。
在 MySQL 中,一个用户可以有很多库。而在 Oracle 中,一个库可以有很多用户,一个用户只能对应一个库。
二、基于 Docker 安装 Oracle
-
拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g
-
下载完成之后可以查看一下是否拉取镜像成功
docker images
-
创建容器
#-d:后台运行容器。 #--privileged: 允许挂载数据卷,默认是读写权限rw #-p 1521:1521:将容器的 1521 端口映射到宿主机的 1521 端口。 #--name oracle11g:为该容器命名为 oracle11g。 #oracle 数据文件挂载:-v /data/dockerData/oracle:/data/oracle,将容器中的数据文件夹 /data/oracle 挂载到宿主机对应的 /data/dockerData/oracl 文件夹中。 #registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g:使用之前拉取的镜像。 docker run -d --privileged -p 1521:1521 --name oracle11g --restart=always -v /home/oracle:/data/oracle registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g
-
进入容器内部进行配置
#1.进入容器 docker exec -it oracle11g bash#2.切换到root用户 su root#3.输入密码:默认helowin#4.配置环境变量 vi /etc/profile#5.在文末添加以下内容 #设置 Oracle 数据库的安装目录 export ORACLE_HOME=/home/oracle/app/oracle/product/11.2.0/dbhome_2 #设置 Oracle 实例名 #这里设置为默认的实例名 "helowin",我尝试修改,但是不管用 export ORACLE_SID=helowin # 将 ORACLE_HOME/bin 添加到 PATH 环境变量中 export PATH=$ORACLE_HOME/bin:$PATH#6.保存后,在容器内重新加载环境变量 source /etc/profile#7.在容器内创建软连接 ln -s $ORACLE_HOME/bin/sqlplus /usr/bin#8.切换到oracle用户 su - oracle#9.使用dba用户登录数据库,创建普通用户 #命令启动 sqlplus sqlplus /nolog #连接数据库并使用 SYSDBA 权限 conn /as sysdba #修改管理员账户system的密码 # 这里将密码设置为 123456(可以自行修改为更复杂的密码) alter user system identified by 123456; #修改管理员账户sys密码 alter user sys identified by 123456; #创建普通用户test并设置其密码为123456 create user test identified by 123456; #这里我们为新创建的 test 用户授予了 DBA 权限,使其能够进行数据库的管理操作,可以根据实际需求调整授予的权限 grant connect, resource, dba to test; #设置密码永不过期,Oracle 默认有一个密码过期策略,这里我们将密码策略设置为永不过期 ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED; #修改数据库最大连接数,需要重启数据库后才能生效 alter system set processes=1000 scope=spfile;#10.在容器内重启数据库 conn /as sysdba #关闭数据库 shutdown immediate; #启动数据库 startup;
-
使用数据库管理工具测试是否可以连接
三、数据库初始化流程
-
创建表空间
#第一次使用数据库的时候一定要给数据库创建表空间 #这个SQL的意思是创建表空间,表空间的位置是哪里,表空间的初始大小是多少,表空间满了选择扩容模式,每次扩容10M create tablespace waterboss datafile '数据文件名.dbf' size 100M autoextend on next 10M;
-
创建用户,授予权限
#创建用户,指定密码,指定表空间 create user 用户名 identified by 密码 default tablespace waterboss;#授予用户dba权限 grant dba to 用户名;
-
创建表
--建立价格区间表 create table t_pricetable ( id number primary key, price number(10,2), ownertypeid number, minnum number, maxnum number ); --业主类型 create table t_ownertype ( id number primary key, name varchar2(30) ); --业主表 create table t_owners ( id number primary key, name varchar2(30), addressid number, housenumber varchar2(30), watermeter varchar2(30), adddate date, ownertypeid number ); --区域表 create table t_area ( id number, name varchar2(30) ); --收费员表 create table t_operator ( id number, name varchar2(30) ); --地址表 create table t_address ( id number primary key, name varchar2(100), areaid number, operatorid number ); --账务表-- create table t_account ( id number primary key, owneruuid number, ownertype number, areaid number, year char(4), month char(2), num0 number, num1 number, usenum number, meteruser number, meterdate date, money number(10,2), isfee char(1), feedate date, feeuser number ); create sequence seq_account;
-
插入数据
--业主类型 insert into t_ownertype values(1,'居民'); insert into t_ownertype values(2,'行政事业单位'); insert into t_ownertype values(3,'商业'); --地址信息-- insert into t_address values( 1,'明兴花园',1,1); insert into t_address values( 2,'鑫源秋墅',1,1); insert into t_address values( 3,'华龙苑南里小区',2,2); insert into t_address values( 4,'河畔花园',2,2); insert into t_address values( 5,'霍营',2,2); insert into t_address values( 6,'回龙观东大街',3,2); insert into t_address values( 7,'西二旗',3,2); --业主信息 insert into t_owners values(1,'范冰',1,'1-1','30406',to_date('2015-04-12','yyyy-MM-dd'),1 ); insert into t_owners values(2,'王强',1,'1-2','30407',to_date('2015-02-14','yyyy-MM-dd'),1 ); insert into t_owners values(3,'马腾',1,'1-3','30408',to_date('2015-03-18','yyyy-MM-dd'),1 ); insert into t_owners values(4,'林小玲',2,'2-4','30409',to_date('2015-06-15','yyyy-MM-dd'),1 ); insert into t_owners values(5,'刘华',2,'2-5','30410',to_date('2013-09-11','yyyy-MM-dd'),1 ); insert into t_owners values(6,'刘东',2,'2-2','30411',to_date('2014-09-11','yyyy-MM-dd'),1 ); insert into t_owners values(7,'周健',3,'2-5','30433',to_date('2016-09-11','yyyy-MM-dd'),1 ); insert into t_owners values(8,'张哲',4,'2-2','30455',to_date('2016-09-11','yyyy-MM-dd'),1 ); insert into t_owners values(9,'昌平区中西医结合医院',5,'2-2','30422',to_date('2016-10-11','yyyy-MM-dd'),2 ); insert into t_owners values(10,'美廉美超市',5,'4-2','30423',to_date('2016-10-12','yyyy-MM-dd'),3 ); --操作员 insert into t_operator values(1,'马小云'); insert into t_operator values(2,'李翠花'); --地区-- insert into t_area values(1,'海淀'); insert into t_area values(2,'昌平'); insert into t_area values(3,'西城'); insert into t_area values(4,'东城'); insert into t_area values(5,'朝阳'); insert into t_area values(6,'玄武'); --价格表-- insert into t_pricetable values(1,2.45,1,0,5); insert into t_pricetable values(2,3.45,1,5,10); insert into t_pricetable values(3,4.45,1,10,null); insert into t_pricetable values(4,3.87,2,0,5); insert into t_pricetable values(5,4.87,2,5,10); insert into t_pricetable values(6,5.87,2,10,null); insert into t_pricetable values(7,4.36,3,0,5); insert into t_pricetable values(8,5.36,3,5,10); insert into t_pricetable values(9,6.36,3,10,null); --账务表-- insert into t_account values( seq_account.nextval,1,1,1,'2012','01',30203,50123,0,1,sysdate,34.51,'1',to_date('2012-02-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','02',50123,60303,0,1,sysdate,23.43,'1',to_date('2012-03-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','03',60303,74111,0,1,sysdate,45.34,'1',to_date('2012-04-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','04',74111,77012,0,1,sysdate,52.54,'1',to_date('2012-05-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','05',77012,79031,0,1,sysdate,54.66,'1',to_date('2012-06-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','06',79031,80201,0,1,sysdate,76.45,'1',to_date('2012-07-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','07',80201,88331,0,1,sysdate,65.65,'1',to_date('2012-08-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','08',88331,89123,0,1,sysdate,55.67,'1',to_date('2012-09-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','09',89123,90122,0,1,sysdate,112.54,'1',to_date('2012-10-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','10',90122,93911,0,1,sysdate,76.21,'1',to_date('2012-11-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','11',93911,95012,0,1,sysdate,76.25,'1',to_date('2012-12-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,1,1,1,'2012','12',95012,99081,0,1,sysdate,44.51,'1',to_date('2013-01-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','01',30334,50433,0,1,sysdate,34.51,'1',to_date('2013-02-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','02',50433,60765,0,1,sysdate,23.43,'1',to_date('2013-03-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','03',60765,74155,0,1,sysdate,45.34,'1',to_date('2013-04-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','04',74155,77099,0,1,sysdate,52.54,'1',to_date('2013-05-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','05',77099,79076,0,1,sysdate,54.66,'1',to_date('2013-06-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','06',79076,80287,0,1,sysdate,76.45,'1',to_date('2013-07-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','07',80287,88432,0,1,sysdate,65.65,'1',to_date('2013-08-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','08',88432,89765,0,1,sysdate,55.67,'1',to_date('2013-09-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','09',89765,90567,0,1,sysdate,112.54,'1',to_date('2013-10-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','10',90567,93932,0,1,sysdate,76.21,'1',to_date('2013-11-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','11',93932,95076,0,1,sysdate,76.25,'1',to_date('2013-12-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,2,1,3,'2012','12',95076,99324,0,1,sysdate,44.51,'1',to_date('2014-01-14','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,100,1,3,'2012','12',95076,99324,0,1,sysdate,44.51,'1',to_date('2014-01-01','yyyy-MM-dd'),2 ); insert into t_account values( seq_account.nextval,101,1,3,'2012','12',95076,99324,0,1,sysdate,44.51,'1',to_date('2015-01-01','yyyy-MM-dd'),2 ); update t_account set usenum=num1-num0; update t_account set money=usenum*2.45; commit;
四、数据类型
类型 | |||
---|---|---|---|
字符类型 | |||
CHAR | 固定长度的字符类型 (存储的长度不够会用空格补齐) | 最大存储 2000 个字节 | |
VARCHAR2 | 可变长度的字符类型 (存储的长度不够不会用空格补齐) | 最大存储 4000 个字节 | |
LONG | 大文本类型 | 最大存储 2 个 G | |
数值型 | |||
NUMBER | NUMBER | 最大可以存储 18 位 | |
NUMBER(5) | 最大可以存储 99999 | ||
NUMBER(5,2) | 最大可以存储 999.99 | ||
日期型 | |||
DATE | 日期时间型 | 精确到秒 | |
TIMESTAMP | 精确到秒的后 9 位 | ||
二进制型 | |||
CLOB | 存储字符(为了弥补 Long 的大小缺陷) | 最大可以存储 4 个 G | |
BLOB | 存储图像、省心、视频等二进制数据 | 最大可以存储 4 个 G |
五、DDL 语句(数据定义语言)
-
创建表
--[xx]是可省略内容 create table 表名(列名 数据类型[长度] [约束],... );
-
修改表
--2.1修改表名 ALTER TABLE 原表名 RENAME TO 新表名;--2.2删除表 drop table 表名;--2.3追加字段 alter table 表名 add(列名 数据类型[长度] [约束],... );--2.4修改字段 alter table 表名 modify (列名 数据类型[长度] [约束],... );--2.5修改字段名 ALTER TABLE 表名 RENAME column 原列名 TO 新列名;--2.6删除字段 alter table 表名 drop column 列名1,列名2...;
六、DML 语句(数据操作语言)
增删改查都是 DML 语句,但是由于查询较为复杂,因此这里只写了增删改。
-
增加数据
--[xx]是可省略内容 insert into 表名 [(列名1,列名2...)] values(值1,值2,值3...);
-
修改数据
update 表名 set 字段1=值1,字段2=值2,...where 条件;
-
删除数据
delete from 表名 where 条件;truncate table 表名;/*说明:1.delete:删除数据是把表里的数据移动到了回滚段里面了,因此可以rollback回滚。所以delete删除可能产生碎片,并且不释放空间。2.truncate:是先摧毁表结构,然后再重建表结构,因此不可以回滚,也不需要提交事务。3.整表删除truncate效率更高。 */
七、程序连接 Oracle 数据库
-
创建一个 SpringBoot 工程
-
引入依赖(这里用的是 java21 的)
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.4</version></dependency><dependency><groupId>com.oracle.database.jdbc</groupId><artifactId>ojdbc11</artifactId><scope>runtime</scope></dependency></dependencies>
-
配置数据源
spring:datasource:url: jdbc:oracle:thin:@//localhost:1521/SIDusername: 用户名password: 密码driver-class-name: oracle.jdbc.OracleDriver
-
编写测试 controller
八、数据迁移-数据导出与导入
-
整库导出/导入命令
--整库导出 参数 full=y 表示整库导出 exp dba用户名/dba密码 full=y [file=文件名.dmp]--整库导入 [已经存在的对象不会继续导入] imp dba用户名/dba密码 full=y [file=文件名.dmp]
-
按用户导入/导出
--整库导出 参数 fowner=用户名 表示导出指定用户的下的表 exp dba用户名/dba密码 owner=用户名 [file=文件名.dmp]--整库导入 [已经存在的对象不会继续导入] imp dba用户名/dba密码 owner=用户名 [file=文件名.dmp]
-
按表导入/导出
--整库导出 参数 tables=表名1,表名2... 表示导出指定表 exp 普通用户名/密码 tables=表名1,表名2... [file=文件名.dmp]--整库导入 [已经存在的对象不会继续导入] imp 普通用户名/密码 tables=表名1,表名2... [file=文件名.dmp]
九、单表查询
大多数同 MySQL 一样,不过多花费时间记录。只记录之前没有了解过的。
-
基于伪列的查询
伪列:在的表使用过程中,我们没有自己去创建,但是实际存在的附加列。伪列只能查询不能进行增删改操作。这里只记录两个伪列的使用:
RowID
和RowNum
。-
ROWID
表中的每一行数据在数据文件中都有一个物理地址。ROWID 返回的是改行的物理地址。ROWID 值可以唯一的标识表中的一行。
select rowid,a.* from t_pricetable a;
-
ROWNUM
在查询的结果集中,ROWNUM 为查询结果集中每一行标识一个行号。确定结果集之后就赋予ROWNUM了
select rownum,a.* from t_pricetable a;
-
十、多表连接查询
-
内连接
--只显示两个表关联上的信息 select a.*,b.* from a,b where a.xxx=b.xxx;
-
左外连接
--左表信息不管是否关联上全部显示 --写法1 select a.*,b.* from a left join b on a.xxx=b.xxx where b.xxx is null; --写法2 select a.*,b.* from a,b where a.xxx=b.xxx(+);
-
右外连接
--右表信息不管是否关联上全部显示 --写法1 select a.*,b.* from a right join b on a.xxx=b.xxx where a.xxx is null; --写法2 select a.*,b.* from a,b where a.xxx(+)=b.xxx;
十一、子查询
写法和MySQL一样,不作详细记录。
- where子句中的子查询
- from子句中的子查询
- select子句中的子查询
十二、分页查询
-
简单分页查询
--查询第1页记录,每页10条 SELECT * FROM t_account WHERE ROWNUM <= 10; --查询第2页记录,每页10条 SELECT * FROM t_account WHERE ROWNUM <= 20 AND ROWNUM > 10;--这个是错误的,查不出来数据 /*特别说明:rownum后面的运算符只能是 < 或<= */--问题:那么查询第2页记录,每页10条,这个该怎么用呢? --答:可以用子查询:先查询所有rownum,然后把这个语句作为子查询 SELECT * FROM ( SELECT ROWNUM AS r, a.* FROM t_account a ) b WHERE b.r > 10 AND b.r <= 20;
-
基于排序的分页查询
--要求:查询排序后查询第1页记录,每页10条 select * from (select rownum as r,a.* from t_account a order by usenum desc) b where b.r>10 and b.r<=20;--错误语句/*说明:rownum 在确定结果之后就赋值了,优先级高于order by 因此出来的结果不对*/ --解决方法:再多套一层 SELECT * FROM ( SELECT ROWNUM AS r, a.* FROM (select * from t_account ORDER BY usenum DESC) a ) b WHERE b.r <= 10;
十三、常用函数
-
字符函数
与字符串运算相关的函数
-
获取字符串长度:
LENGTH('字符串')
select length('abc') from dual;--结果:3
-
截取字符串内容:
substr('字符串',截取开始位置,截取长度)
--位置从1开始,不是从0开始 select substr('1234567890',2,3) from dual;--结果:234
-
字符串拼接:
concat('字符串1','字符串2')
或||
select concat('1','23') from dual;--结果:123--说明:也可以使用 || 进行拼接 select '1'||'23' from dual;--结果:123
-
其他方法参见下面的图片,就不一一举例了
-
-
数值函数
-
四舍五入函数:
round(数字,[保留小数位])
--1.四舍五入返回整数 select round(123.546) from dual;--返回124 --1.四舍五入返回2位小数 select round(123.546,2) from dual;--返回123.55
-
数字截取:
trunc(数字)
--1.截取整数位 select trunc(123.546) from dual;--返回123 --1.截取整数位后的两位 select round(123.546,2) from dual;--返回123.54
-
取模:
mod(被除数,除数)
select round(10,3) from dual;--返回1
-
其他方法参见下面的图片,就不一一举例了
-
-
日期函数
-
获取系统当前日期和时间:
sysdate
select sysdate from dual;--年月日 时分秒
-
加月函数:
add_months(时间,多少个月)
select add_months(sysdate,3) from dual;--当前时间加三个月
-
日期所在月的最后一天:
last_day(日期)
select last_day(sysdate) from dual;
-
日期截取
trunc(日期)
select trunc(sysdate) from dual;--截取掉时间,只剩下年月日 2025-03-19 select trunc(sysdate,'mm') from dual;--截取掉月份后面的,返回当月第一天 2025-03-01 select trunc(sysdate,'yyyy') from dual;--截取掉年后面的,返回当年第一天 2025-01-01
-
-
转换函数
-
数字转字符串:
to_char(数字)
--方式1 select to_char(100) from dual;--将数字转为字符串--方式2 select 100 ||'' from dual;--将数字转为字符串
-
日期转字符串:
to_char(日期,'格式')
select to_char(sysdate,'yyyy-mm-dd') from dual;--转化为年月日 select to_char(sysdate,'yyyy') from dual;--转化为年 select to_char(sysdate,'mm') from dual;--转化为月 select to_char(sysdate,'dd') from dual;--转化为日 select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual;--转化为年月日
-
字符串转日期:
to_date('日期字符串','格式')
select to_date('2025-03-19','yyyy-mm-dd') from dual;--转化字符串为日期
-
字符串转数字:
to_number('字符串')
--方式1 select to_number('100') from dual;--转化字符串为数字--方式2 select '100'+0 from dual;--转化字符串为数字
-
其他方法参见下面的图片,就不一一举例了
-
-
其他函数
-
空值处理函数:
nvl(需要检测的值,为null返回值)
或nvl2(需要检测的值,不为null返回值,为null返回值)
--nvl(需要检测的值,为null返回值):如果被检测值是空,则返回设置的默认值 select nvl(null,100) from dual;--返回100--nvl2(需要检测的值,不为null返回值,为null返回值):如果被检测值是空的,返回一个值,如果不为空,返回另一个值 select nvl2(null,100,200) from dual;--返回200 select nvl2(399,100,200) from dual;--返回100
-
条件取值:
decode(条件,值1,返回值1,值2,返回值2...都不合符返回的默认值)
--decode(条件,值1,返回值1,值2,返回值2...都不合符返回的默认值):比较条件跟后面的哪个值匹配,如果匹配上了返回对应的值,否则返回设置的默认值 select decode(4,1,100,2,200,3,300,500) from dual;--匹配不上,返回500
-
条件取值:
case when then
--case when then end类似于java中的switch-case,可以达到decode的效果 --写法1 select name,(case zhiyewhen 1 then '老师'when 2 then '学生'when 3 then '宿管'else '其他'end) from t_owners; --写法2 select name,(casewhen zhiye=1 then '老师'when zhiye=2 then '学生'when zhiye=3 then '宿管'else '其他'end) from t_owners;
-
十四、行列转换
可以使用decode或case-when,不满足条件的不进行计算,具体如下图
十五、分析函数
-
值相同,排名相同,后面的序号跳跃
说明:值相同的,他们的排名就相同,如果出现值不同的了,排名直接跳着显示。
案例:班里期末考试,1个100分,2个98分,3个95分,问98分排第几名,95分排第几名
答:98分并列第二名,95分并列第四名
--rank() over(排序语句)函数 select rank() over (order by usenum desc) 排名,a.* from t_account a;
-
值相同,排名相同,后面的序号连续
说明:值相同的,他们的排名就相同,如果出现值不同的了,排名接着上面的继续。
案例:班里期末考试,1个100分,2个98分,3个95分,问98分排第几名,95分排第几名
答:98分并列第二名,95分并列第3名
--dense_rank over(排序语句)函数 select dense_rank() over (order by usenum desc) 排名,a.* from t_account a;
-
序号连续,不管值是否相同
说明:值相同,但是排名不一样,依次排下去
案例:班里期末考试,1个100分,2个98分,3个95分,问98分排第几名,95分排第几名
答:98分排第2,3名,95分并第4,5,6名
--row_number() over(排序语句)函数 select row_number() over (order by usenum desc) 排名,a.* from t_account a;--拓展:这种可以替代rownum进行分页查询 select * from ( select row_number() over (order by usenum desc) 排名,a.* from t_account a) where 排名>=10 and 排名<20;
十六、集合运算
把两个集合进行交、并、差运算
-
并集(不去重):
union all
两个结果集合并,结果集中包含重复元素
select * from a union all select * from b
-
并集(去重):
union
两个结果集合并,结果集中不包含重复元素
select * from a union select * from b
-
交集:
intersect
获取两个结果集的重复记录
select * from a intersect select * from b
-
差集:
minus
从一个结果集中减掉另一个结果集的数据
--a[1,2,3,4,5] b[4,5,6] 结果:1,2,3 select * from a minus select * from b--拓展:可以用差集分页 --获取第2页数据:用前20条数据-前10条数据 select * from a where a.rownum<=20 minus select * from a where a.rownum<=10