今天,在学习Oracle的时候,碰到了一点麻烦
后来,查阅了一些资料,做了点试验。
特此记录下来,与大家分享~
我文笔一般,说的都是大白话~希望大家能看的懂
有的时候,我们经常碰见这样的需求(比如面试的时候...),要求把一个结果集排序后,取得前N条数据的值。
比如 取得某个部门中,工资最高的前10名。在SQLServer中可以通过Order by结合TOP就可以返回相应的数据。但是,在Oracle中没有top这个关键字。那么咱如何实现呢?
Oracle提供了一个rownum的伪列(pseudocolumn),用于标明返回result的次序。比如返回的第一行数据的rownum为1,第2行为2...第N行为N。
首先,我们先建立这样一张表用来做试验:
SQL> CREATE TABLE TESTSORT(id NUMBER);
Table created
接下来,往这个表里INSERT 10条数据(ID从1到10)
SQL> declare
2 type int_table_type is table of int index by binary_integer;
3 int_table int_table_type;
4
5 begin
6
7 for i in 1..10 loop
8 int_table(i):=i;
9 end loop;
10 forall i in 1..int_table.count
11 insert into testsort values(int_table(i));
12 end;
13 /
PL/SQL procedure successfully completed
首先,我们先来看看,每个ID以及他们相应的ROWNUM。
SQL> select id,rownum from testsort order by id;
ID ROWNUM
---------- ----------
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
10 rows selected
现在,我们来取一下 ID最小的前5个值
SQL> select id,rownum from testsort where rownum<=5 order by id;
ID ROWNUM
---------- ----------
1 1
2 2
3 3
4 4
5 5
嗯嗯~看样子是正常显示了我们需要的数据。
不过先不要急,让我们再搞些“破坏”,执行下面的这几条SQL
SQL> delete from testsort where id in (1,2,3);
3 rows deleted
SQL> select id,rownum from testsort;
ID ROWNUM
---------- ----------
4 1
5 2
6 3
7 4
8 5
9 6
10 7
7 rows selected
SQL> insert into testsort values(1);
1 row inserted
SQL> insert into testsort values(2);
1 row inserted
SQL> insert into testsort values(3);
1 row inserted
SQL> select id,rownum from testsort order by id;
ID ROWNUM
---------- ----------
1 8
2 9
3 10
4 1
5 2
6 3
7 4
8 5
9 6
10 7
10 rows selected
我们再执行一下,之前那条SQL
SQL> select id,rownum from testsort where rownum<=5 order by id;
ID ROWNUM
---------- ----------
4 1
5 2
6 3
7 4
8 5
结果是显而易见的,由于2次执行SQL的ROWNUM不一致,因此不能返回正常的数据。
那为什么会这样呢,我们需要理解ORACLE是如何给ROWNUM列赋值的。
Rownum是个伪列,并不是物理存在的,我的理解是先查到结果集之后再加上去的一个列。
那按照什么规则加呢?我们用cursor的观点去看的话,应该更容易理解。
“破坏”数据之前,fetch数据的顺序是 ID=1,2,3,4,5....
因此ID 1 的ROWNUM为1 ,ID 2的ROWNUM为2..以此类推。
所以查询的结果是我们所要的。
“破坏”数据之后,由于对TABLE做了DELETE,INSERT操作,导致fetch的顺序变更了
fetch顺序是 ID=4,5,6...1,2,3 也就是说ID4是最先被取回的数据,因此他的ROWNUM是1,ID5为2,ID1,2,3分别为8,9,10。完了之后,在Order by结果集,当然这个时候再用rownum<=5来过滤的数据就是错误的了。
这个“破坏”只是打个比喻。然而,在项目中对表的CRUD操作必不可少。所以说,像这样的SQL:select id from testsort where rownum<=5 order by id; 是一个陷阱。有一种情况例外,那就是ID为PK的时候,大家可以做下实验。
好了,下面该是如何解决问题的时候了。利用子查询问题就会游刃而解了
SQL> select t.id,rownum from (select * from testsort order by id) t where rownum<=5;
ID ROWNUM
---------- ----------
1 1
2 2
3 3
4 4
5 5
嗯...from 子查询,返回的数据已经是被Order by了的数据了。自然fetch的顺序就是符合条件的。ORDER BY DESC也是一样的。
SQL> select t.id,rownum from (select * from testsort order by id desc) t where rownum<=5;
ID ROWNUM
---------- ----------
10 1
9 2
8 3
7 4
6 5
虽然麻烦,但是貌似目前只能这样处理,如果哪位达人有更好的办法,请帮忙指点
最后,再来说一下Rownum比较操作符的问题。
很多资料都说不支持>,>=,=,between……and,只能用以上符号(<、& lt;=、!=)
虽说不支持,但并不会报Error。只是返回的数据永远为空,原因就是根本不可能满足这样的where条件。
SQL> select t.id,rownum from (select * from testsort order by id) t
where rownum > 5;
ID ROWNUM
---------- ----------
之前说过,取回的第1条数据它的ROWNUM肯定是1。也就是说rownum肯定是从1开始顺番。
如上面这条SQL,取回第1条数据的id为1,rownum为1,然后Oracle一看,哦 1 < 5 ~不满足条件,舍弃了。然后取第2条数据id为2,rownum还是为1,又< 5,再舍弃。以此类推,最终舍弃了所有的数据,因此没有一条满足的,这就是所谓不支持的原因。当然一些符号(如:>=,=)和1比较是没有问题的。
那么怎么解决这个问题呢?比如,需要返回满足条件的 前2~4条数据?
我们可以举一反三,利用子查询依然能够解决这个问题。
--注意要给子查询中的rownum 起别名
select * from (
select t.id,rownum num from (select * from testsort order by id) t where rownum < 5) where num > 1;
最后这里是Oracle对Rownum的解释:
Here
以上是我与大家分享的一些拙见,希望能够帮助到像我这样的Oracle新人们,更好的理解Oracle Rownum~ 欢迎达人们指正~
分享到:
相关推荐
Oracle中rownum的使用
`ROWNUM`在Oracle中是一个强大但需谨慎使用的工具。正确理解其行为逻辑,特别是在处理比较运算符时,是至关重要的。通过合理的设计查询结构,可以充分发挥`ROWNUM`的优势,实现在大型数据集上的高效查询和分页功能。...
ROWNUM是一个序列,是oracle数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则rownum值为1,第二条为2,依次类推。如果你用>,>=,=,between...and这些条件,因为从缓冲区或数据文件中得到的第一条记录的...
"Oracle 中的 ROWNUM 和 DISTINCT" Oracle 中的 ROWNUM 和 DISTINCT 是两个非常重要的关键词,它们在查询数据时发挥着至关重要的作用。然而,许多开发者在使用这两个关键词时,却常常会遇到一些不太理解的地方,...
oracle中rownum在结果集中排序的使用.doc
本文将详细介绍 Oracle 中 ROWNUM 的使用方法,并与 SQL Server 中相应的功能进行对比分析。 #### Oracle ROWNUM 基础用法 1. **ROWNUM 的默认行为:** - 在 Oracle 中,ROWNUM 默认从 1 开始计数,对于每一行...
### Oracle中的ROWNUM使用详解 在Oracle数据库中,`ROWNUM`是一个非常有用的伪列,它可以帮助用户在查询结果集中为每一行分配一个唯一的行号。`ROWNUM`的值从1开始,并随着行的增加而递增。下面将详细介绍`ROWNUM`...
ROWNUM 是 Oracle 中的一种伪列,它可以根据返回记录生成一个序列化的数字。利用 ROWNUM,我们可以生产一些原先难以实现的结果输出,但是因为它是伪列的特殊性,在使用时需要注意一些事项,以免掉入“陷阱”。 特殊...
### Oracle中的ROWNUM使用详解 #### 一、ROWNUM简介 在Oracle数据库中,`ROWNUM`是一个非常有用的伪列,它为查询结果中的每一行分配一个唯一的行号。这个行号从1开始,每增加一行,行号就递增1。`ROWNUM`对于数据...
总之,ROWNUM在Oracle中是一种强大的工具,但它需要谨慎使用,以避免潜在的问题。理解ROWNUM的工作原理,以及如何与其他查询结构结合,是有效利用这一特性的关键。在进行复杂查询时,应始终考虑查询性能和结果的准确...
本文将深入探讨`ORDER BY`子句在Oracle中的排序机制,以及查询时根据`IN`条件顺序输出的方法。 首先,`ORDER BY`用于指定查询结果的排序方式,可以基于一个或多个列进行升序(ASC)或降序(DESC)排序。然而,...
ROWNUM 和排序 在 Oracle 中,ROWNUM 是在取数据的时候产生的序号,所以想对指定排序的数据去指定的 ROWNUM 行数据就必须注意了。例如: ```sql SELECT ROWNUM, id, name FROM student ORDER BY name; ``` 可以...
4. 如果表中的主键是按照升序插入的,且查询中没有`GROUP BY`和`ORDER BY`子句,`ROWNUM`的顺序可能与主键的顺序一致。但这是偶然的,不是`ROWNUM`的固有特性。 5. 在子查询中使用`ROWNUM`并将其传递到外部查询中时...
sql语句中select top n与oracle的rownum与mysql的limit 取前几条数据sql简单用法
Oracle中的ROWNUM是在取数据的时候产生的序号,所以想对指定排序的数据去指定的ROWNUM行数据就必须注意了。例如: ```sql SELECT ROWNUM, ID, NAME FROM STUDENT ORDER BY NAME; ``` 可以看出,ROWNUM并不是按照NAME...
Oracle 中的 ROWNUM 是一个伪列,用于对查询返回的行进行编号,返回的第一行分配的是 1,第二行是 2,以此类推。这个伪列可以用于限制查询返回的总行数。下面我们将通过实例来详细解析 ROWNUM 的使用方法和技巧。 ...
Oracle ROWNUM 伪列详解 Oracle 的 ROWNUM 伪列是一个非常重要的概念,它对结果集加的一个伪列,即先查到结果集之后再加上去的一个列。了解 ROWNUM 的意义是非常重要的,否则可能会出现莫名其妙的结果。 ROWNUM ...
本文主要解决 Oracle 分页查询中排序与效率问题,通过实践和分析,提供了两种解决方案,并对比了两种方法的优缺点。 知识点 1: Oracle 分页查询的基本概念 Oracle 分页查询是指在查询结果中,通过限制行数来实现...
### 在Oracle中灵活使用Rownum和RowId 在Oracle数据库中,`ROWNUM` 和 `ROWID` 是两个非常重要的概念,它们可以帮助我们在查询数据时实现更灵活的数据管理。本文将详细介绍这两个概念的区别及其使用方法,并通过...
总的来说,理解并掌握Oracle中的ROWNUM用法对于编写高效、精确的SQL查询至关重要。正确使用ROWNUM可以帮助我们限制返回的结果集大小,进行分页,以及在特定条件下选择行。但同时也需要注意其在不同情况下的行为差异...