视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Oracle中ROWNUM的使用技巧
2020-11-09 07:38:32 责编:小采
文档


Oracle中ROWNUM的使用技巧 [English] 作者: fuyuncat 来源: www.HelloDBA.com 日期: 2009-02-14 14:54:36 ROWNUM是一种伪列,它会根据返回记录生成一个序列化的数字。利用ROWNUM,我们可以生产一些原先难以实现的结果输出,但因为它是伪列的这个特殊性,

Oracle中ROWNUM的使用技巧

[English]

作者:fuyuncat

来源:www.HelloDBA.com

日期:2009-02-14 14:54:36


ROWNUM是一种伪列,它会根据返回记录生成一个序列化的数字。利用ROWNUM,我们可以生产一些原先难以实现的结果输出,但因为它是伪列的这个特殊性,我们在使用时也需要注意一些事项,不要掉入“陷阱”。下面就介绍一下它的使用技巧及注意事项。

1 特殊结果输出

利用ROWNUM,我们可以做到一些特殊方式的输出。

1.1 Top N结果输出

我们如果希望取输出结果的前面几条数据,通过ROWNUM可以轻松实现:

SQL> select * from t_test4
 2 where rownum <= 5;
 
USERNAME USER_ID CREATED
------------------------------ ---------- ---------
WOW 71 26-APR-07
CS2 70 15-JAN-07
3 69 01-NOV-06
DMP 68 12-OCT-06
PROFILER 67 05-SEP-06

但是,如果你希望对一个排序结果取Top N数据的话,使用ROWNUM存在一些“陷阱”,我们后面部分会介绍这些“陷阱”并且说明如何避免。

1.2 分页查询

利用ROWNUM对结果进行分页,下面返回结果中的第6到第10条记录:

SQL> select * from
 2 (
 3 select a.*, rownum as rn from css_bl_view a
 4 where capture_phone_num = '(1) 925-4604800'
 5 ) b
 6 where b.rn between 6 and 10;
 
6 rows selected.
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2770 Card=2183 Bytes =71667)
 1 0 VIEW (Cost=2770 Card=2183 Bytes=71667)
 2 1 COUNT
 3 2 TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 29346 consistent gets
 29190 physical reads
 0 redo size
 7328 bytes sent via SQL*Net to client
 234 bytes received via SQL*Net from client
 4 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 5 rows processed

另外一种实现方式:

SQL> select * from css_bl_view a
 2 where capture_phone_num = '(1) 925-4604800'
 3 and rownum <= 10
 4 minus
 5 select * from css_bl_view a
 6 where capture_phone_num = '(1) 925-4604800'
 7 and rownum <= 5
 8 ;
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=5920 Card=10 Bytes=70)
 1 0 MINUS
 2 1 SORT (UNIQUE) (Cost=2960 Card=10 Bytes=5980)
 3 2 COUNT (STOPKEY)
 4 3 TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)
 5 1 SORT (UNIQUE) (Cost=2960 Card=5 Bytes=2990)
 6 5 COUNT (STOPKEY)
 7 6 TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 62 consistent gets
 50 physical reads
 0 redo size
 7232 bytes sent via SQL*Net to client
 234 bytes received via SQL*Net from client
 4 SQL*Net roundtrips to/from client
 2 sorts (memory)
 0 sorts (disk)
 5 rows processed

第三种实现方式:

SQL> select * from
 2 (
 3 select a.*, rownum as rn from css_bl_view a
 4 where capture_phone_num = '(1) 925-4604800'
 5 and rownum <= 10
 6 ) b
 7 where b.rn > 5;
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2770 Card=10 Bytes=32830)
 1 0 VIEW (Cost=2770 Card=10 Bytes=32830)
 2 1 COUNT (STOPKEY)
 3 2 TABLE ACCESS (FULL) OF 'CSS_BL_VIEW' (Cost=2770 Card=2183 Bytes=1305434)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 35 consistent gets
 30 physical reads
 0 redo size
 7271 bytes sent via SQL*Net to client
 234 bytes received via SQL*Net from client
 4 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 5 rows processed

这里特地将三种实现方式的查询计划及统计数据打印出来,大家可以比较一下3中方式的性能。

1.3 利用ROWNUM做分组子排序

对于以下表T_TEST4的内容:

OWNER NAME
------------------------------------------------------
STRMADMIN STREAMS_QUEUE
APARKMAN JOB_QUEUE
SYS AQ$_AQ_SRVNTFN_TABLE_E
SYS AQ$_KUPC$DATAPUMP_QUETAB_E
APARKMAN AQ$_JMS_TEXT_E
STRMADMIN AQ$_STREAMS_QUEUE_TABLE_E
SYS AQ$_SCHEDULER$_EVENT_QTAB_E

如果我们希望结果按照OWNER进行分组后,再对每组中成员进行编号,结果类似如下:

OWNER NO NAME
------------------------------------------------------
APARKMAN 1 JOB_QUEUE
 2 AQ$_JMS_TEXT_E
STRMADMIN 1 STREAMS_QUEUE
 2 AQ$_STREAMS_QUEUE_TABLE_E
SYS 1 AQ$_AQ_SRVNTFN_TABLE_E
 2 AQ$_KUPC$DATAPUMP_QUETAB_E
 3 AQ$_SCHEDULER$_EVENT_QTAB_E

在没有ROWNUM时要实现这样的功能会很复杂,但通过ROWNUM我们可以轻松实现:

SQL> SELECT DECODE(ROWNUM-min_sno,0,a.owner,NULL) owner,DECODE(ROWNUM-min_sno,0,1,rownum+1-min_sno) sno, a.name
 2 FROM (SELECT *
 3 FROM t_test8
 4 ORDER BY owner, name ) a,
 5 (SELECT owner, MIN(rownum) min_sno
 6 FROM( SELECT *
 7 FROM t_test8
 8 ORDER BY owner, name)
 9 GROUP BY owner) b
 10 WHERE a.owner=b.owner;
 
OWNER SNO NAME
------------------------------ ---------- ------------------------------
APARKMAN 1 JOB_QUEUE
 2 AQ$_JMS_TEXT_E
STRMADMIN 1 STREAMS_QUEUE
 2 AQ$_STREAMS_QUEUE_TABLE_E
SYS 1 AQ$_AQ_SRVNTFN_TABLE_E
 2 AQ$_KUPC$DATAPUMP_QUETAB_E
 3 AQ$_SCHEDULER$_EVENT_QTAB_E
 4 AQ$_SCHEDULER$_JOBQTAB_E
 5 AQ$_STREAMS_QUEUE_TABLE_E
 6 AQ$_SYS$SERVICE_METRICS_TAB_E
 7 AQ$_AQ_EVENT_TABLE_E
 8 AQ$_AQ$_MEM_MC_E
 9 AQ$_ALERT_QT_E
 10 ALERT_QUE
 11 AQ_EVENT_TABLE_Q
 12 SYS$SERVICE_METRICS
 13 STREAMS_QUEUE
 14 SRVQUEUE
 15 SCHEDULER$_JOBQ
 16 SCHEDULER$_EVENT_QUEUE
 17 AQ_SRVNTFN_TABLE_Q
SYSMAN 1 AQ$_MGMT_NOTIFY_QTABLE_E
 2 MGMT_NOTIFY_Q
SYSTEM 1 DEF$_AQERROR
 2 DEF$_AQCALL
 3 AQ$_DEF$_AQERROR_E
 4 AQ$_DEF$_AQCALL_E
WMSYS 1 AQ$_WM$EVENT_QUEUE_TABLE_E
 2 WM$EVENT_QUEUE
 
29 rows selected.

2 性能

我们很多程序员在确认某个表中是否有相应数据时,喜欢加上ROWNUM=1,其思路就是只要存在一条数据就说明有相应数据,查询就可以直接返回了,这样就能提高性能了。但是在10G之前,使用ROWNUM=1是不能达到预期的性能效果的,而是需要通过<2或<=1作为过滤条件才能达到预期效果,看以下查询计划:

SQL> select * from t_test1
 2 where object_id <100
 3 and rownum = 1;
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=86)
 1 0 COUNT (STOPKEY)
 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=37 Card= Bytes=7654)
 3 2 INDEX (RANGE SCAN) OF 'T_TEST1_PK' (UNIQUE) (Cost=2 Card=)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 62 consistent gets
 0 physical reads
 0 redo size
 654 bytes sent via SQL*Net to client
 234 bytes received via SQL*Net from client
 4 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 1 rows processed
 
SQL> select * from t_test1
 2 where object_id <100
 3 and rownum <= 1;
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=86)
 1 0 COUNT (STOPKEY)
 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=37 Card= Bytes=7654)
 3 2 INDEX (RANGE SCAN) OF 'T_TEST1_PK' (UNIQUE) (Cost=2 Card=)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 3 consistent gets
 0 physical reads
 0 redo size
 654 bytes sent via SQL*Net to client
 234 bytes received via SQL*Net from client
 4 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 1 rows processed
 
SQL> /
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=37 Card=1 Bytes=86)
 1 0 COUNT (STOPKEY)
 2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_TEST1' (Cost=37 Card= Bytes=7654)
 3 2 INDEX (RANGE SCAN) OF 'T_TEST1_PK' (UNIQUE) (Cost=2 Card=)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 3 consistent gets
 0 physical reads
 0 redo size
 654 bytes sent via SQL*Net to client
 234 bytes received via SQL*Net from client
 4 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 1 rows processed

10G以后,这个问题就被修正了:

SQL> select * from t_test1
 2 where rownum = 1;
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 5363188
 
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 86 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| T_TEST1 | 1 | 86 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
 1 - filter(ROWNUM=1)
 
 
Statistics
----------------------------------------------------------
 1 recursive calls
 0 db block gets
 4 consistent gets
 1 physical reads
 0 redo size
 1201 bytes sent via SQL*Net to client
 385 bytes received via SQL*Net from client
 2 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 1 rows processed
 
SQL> select * from t_test1
 2 where rownum <= 1;
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 5363188
 
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 86 | 2 (0)| 00:00:01 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS FULL| T_TEST1 | 1 | 86 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
 1 - filter(ROWNUM<=1)
 
 
Statistics
----------------------------------------------------------
 0 recursive calls
 0 db block gets
 4 consistent gets
 0 physical reads
 0 redo size
 1201 bytes sent via SQL*Net to client
 385 bytes received via SQL*Net from client
 2 SQL*Net roundtrips to/from client
 0 sorts (memory)
 0 sorts (disk)
 1 rows processed

3 ROWNUM的使用“陷阱”

由于ROWNUM是一个伪列,只有有结果记录时,ROWNUM才有相应数据,因此对它的使用不能向普通列那样使用,否则就会陷入一些“陷阱”当中。

3.1 对ROWNUM进行>、>=、=操作

不能对ROWNUM使用>(大于1的数值)、>=(大于或等于1的数值)、=(大于或等于1的数值),否则无结果

SQL> select count(*) from css_bl_view a where rownum>0;
 
 COUNT(*)
----------
361928
 
 
SQL> select count(*) from css_bl_view a
 2 where rownum > 1;
 
 COUNT(*)
----------
 0

这是因为:

1、ROWNUM是伪列,必须要要有返回结果后,每条返回记录就会对应产生一个ROWNUM数值;

2、返回结果记录的ROWNUM是从1开始排序的,因此第一条始终是1;

这样,当查询到第一条记录时,该记录的ROWNUM为1,但条件要求ROWNUM>1,因此不符合,继续查询下一条;因为前面没有符合要求的记录,因此下一条记录过来后,其ROWNUM还是为1,如此循环,就不会产生结果。上述查询可以通过子查询来替代:

SQL> select count(*)
 2 from
 3 (select BL_REF_CDE, rownum rn from css_bl_view)
 4 where rn > 1;
 
 COUNT(*)
----------
 361927

我们可以通过以下方式来实现对ROWNUM的>、=的查询:

查询ROWNUM=5的数据:

SQL> select object_id,object_name
 2 from (select object_id,object_name, rownum as rn from t_test1)
 3 where rn = 5;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
 29 C_COBJ#

查询ROWNUM > 25的数据:

SQL> select * from t_test4
 2 minus
 3 select * from t_test4
 4 where rownum <= 25;
 
USERNAME USER_ID CREATED
------------------------------ ---------- ---------
DIP 19 21-NOV-05
OUTLN 11 21-NOV-05
PUBLIC 99999 18-JUL-07
SYS 0 21-NOV-05
SYSMAN 32 21-NOV-05
SYSTEM 5 21-NOV-05
 
6 rows selected.

3.2 ROWNUM和Order BY

要注意的是:在使用ROWNUM时,只有当Order By的字段是主键时,查询结果才会先排序再计算ROWNUM,下面OBJECT_ID是表T_TEST1的主键字段:

SQL> select object_id,object_name from t_test1
 2 where rownum <= 5
 3 order by object_id;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
 2 C_OBJ#
 3 I_OBJ#
 4 TAB$
 5 CLU$
 6 C_TS#

但是,对非主键字段OBJECT_NAME进行排序时,结果就混乱了:

SQL> select object_id,object_name from t_test1
 2 where rownum <= 5
 3 order by object_name;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
 28 CON$
 29 C_COBJ#
 20 ICOL$
 44 I_USER1
 15 UNDO$
 
SQL> select count(*) from t_test1
 2 where object_name < 'CON$';
 
 COUNT(*)
----------
 215

出现这种混乱的原因是:Oracle先按物理存储位置(rowid)顺序取出满足rownum条件的记录,即物理位置上的前5条数据,然后在对这些数据按照Order By的字段进行排序,而不是我们所期望的先排序、再取特定记录数。

如果需要对非主键字段排序再去前n条数据,我们可以以以下方式实现:

SQL> select object_id,object_name
 2 from (select object_id,object_name from t_test1
 3 order by object_name)
 4 where rownum <= 5;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
 354 /1000e8d1_LinkedHashMapValueIt
 35490 /1000e8d1_LinkedHashMapValueIt
 21801 /1005bd30_LnkdConstant
 21802 /1005bd30_LnkdConstant
 17205 /10076b23_OraCustomDatumClosur

3.3 排序分页

当对存在重复值的字段排序后再分页输出,我们很容易会陷入到另外一个“陷阱”。

请看以下例子,我们希望对T_TEST1的OWNER字段排序后,以每页输出10个结果的方式分页输出:

SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name from t_test1 order by owner) a
 4 where rownum <= 10)
 5 where rn >= 1;
 
OWNER OBJECT_NAME
------------------------------ ------------------------------
AFWOWNER AFWADAPTER
AFWOWNER AFWADAPTERCONFIGURATION
AFWOWNER AFWADAPTERCONFIGURATION_IDX1
AFWOWNER AFWADAPTERFQN_PK
AFWOWNER AFWADAPTERCONFIGURATION_PK
AFWOWNER AFWADAPTERCONFIGURATION_IDX2
AFWOWNER AFWSERVERCODE_PK
AFWOWNER AFWSERVER
AFWOWNER AFWADAPTERLOOKUP_IDX1
AFWOWNER AFWADAPTERLOOKUP
 
10 rows selected.
 
SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name from t_test1 order by owner) a
 4 where rownum <= 20)
 5 where rn >= 11;
 
OWNER OBJECT_NAME
------------------------------ ------------------------------
AFWOWNER AFWTOKENSTATUSCODE_PK
AFWOWNER AFWTOKENSTATUS
AFWOWNER AFWTOKENADMIN_IDX1
AFWOWNER AFWTOKENADMINCODE_PK
AFWOWNER AFWTOKENADMIN
AFWOWNER AFWTOKEN
AFWOWNER AFWSERVERCONFIGURATION_PK
AFWOWNER AFWSERVERCONFIGURATION
AFWOWNER AFWSERVER
AFWOWNER AFWADAPTERLOOKUP
 
10 rows selected.

仔细比较结果,你会发现“AFWSERVER”、“AFWADAPTERLOOKUP”在两次分页结果中都出现了。但是OBJECT_NAME在每个OWNER中的值是唯一的,说明这个输出结果是错误的,我们又陷入了一个“陷阱”。这是怎么回事呢,请先看下上述语句的查询计划:

SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name from t_test1 order by owner) a
 4 where rownum <= 20)
 5 where rn >= 11;
 
10 rows selected.
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=205 Card=20 Bytes=94
 0)
 
 1 0 VIEW (Cost=205 Card=20 Bytes=940)
 2 1 COUNT (STOPKEY)
 3 2 VIEW (Cost=205 Card=30670 Bytes=1042780)
 4 3 SORT (ORDER BY STOPKEY) (Cost=205 Card=30670 Bytes=858760)
 5 4 TABLE ACCESS (FULL) OF 'T_TEST1' (Cost=42 Card=30670 Bytes=858760)

看下这个“陷阱”是怎么形成的。从查询计划上,我们可以注意到,对于子查询

select a.*, rownum as rn from
 (select owner, object_name from t_test1 order by owner) a
where rownum <= 20

优化器采用了“SORT (ORDER BY STOPKEY)”。

“SORT (ORDER BY STOPKEY)”不需要对所有数据进行排序,而是只要找出结果集中的按特定顺序的最前N条记录,一旦找出了这N条记录,就无需再对剩下的数据进行排序,而直接返回结果。这种算法我们可以视为是“快速排序”算法的变种。快速排序算法的基本思想是:先将数据分2组集合,保证第一集合中的每个数据都大于第二个集合中每个数据,然后再按这个原则对每个集合进行递归分组,直到集合的单位最小。在进行“SORT (ORDER BY STOPKEY)”时,首先找出N条数据(这些数据并没有做排序)放在第一组,保证第一组的数据都大于第二组的数据,然后只对第一组数据进行递归。

可以看到,基于这样的算法基础上,如果N的数值不同,数据的分组也不同(如N=20时,第一次分组比例为12:8,然后继续递归;当N=10时,第一次分组比例为3:7 … …),这样,在数据的排序字段值都相等时,输出结果的顺序就会因为N值不同而不同。

知道原因后,我们可以通过以下几种方法来避免这个“陷阱”。

1、让查询计划避免“SORT (ORDER BY STOPKEY)”,采用“SORT (ORDER BY)”,使数据排序不受ROWNUM的影响。但这样会使所有数据都做排序:

SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name, rowid from t_test1 order by owner) a)
 4 where rn <= 10
 5 and rn >= 1;
 
OWNER OBJECT_NAME
------------------------------ ------------------------------
AFWOWNER AFWADAPTER
AFWOWNER AFWADAPTERCONFIGURATION
AFWOWNER AFWADAPTERCONFIGURATION_IDX2
AFWOWNER AFWADAPTERCONFIGURATION_PK
AFWOWNER AFWADAPTERCONFIGURATION_IDX1
AFWOWNER AFWADAPTERFQN_PK
AFWOWNER AFWADAPTERLOOKUP_IDX1
AFWOWNER AFWSERVERCODE_PK
AFWOWNER AFWSERVERCONFIGURATION_IDX1
AFWOWNER AFWTOKENTYPECODE_PK
 
10 rows selected.
 
SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name, rowid from t_test1 order by owner) a)
 4 where rn <= 20
 5 and rn >= 11;
 
OWNER OBJECT_NAME
------------------------------ ------------------------------
AFWOWNER AFWTOKENTYPE
AFWOWNER AFWTOKENSTATUSCODE_PK
AFWOWNER AFWTOKENSTATUS
AFWOWNER AFWTOKENADMIN_IDX1
AFWOWNER AFWTOKENADMINCODE_PK
AFWOWNER AFWTOKENADMIN
AFWOWNER AFWTOKEN
AFWOWNER AFWSERVERCONFIGURATION_PK
AFWOWNER AFWTOKEN_PK
AFWOWNER AFWTOKEN_IDX6
 
10 rows selected.
 
SQL> set autot trace
SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name, rowid from t_test1 order by owner) a)
 4 where rn <= 20
 5 and rn >= 11;
 
10 rows selected.
 
 
Execution Plan
----------------------------------------------------------
 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=237 Card=30670 Bytes=1441490)
 1 0 VIEW (Cost=237 Card=30670 Bytes=1441490)
 2 1 COUNT
 3 2 VIEW (Cost=237 Card=30670 Bytes=1042780)
 4 3 SORT (ORDER BY) (Cost=237 Card=30670 Bytes=1073450)
 5 4 TABLE ACCESS (FULL) OF 'T_TEST1' (Cost=42 Card=30670 Bytes=1073450)

2、在排序时,加上一个或多个字段(如主键字段、ROWID),使排序结果具有唯一性:

SQL> select owner, object_name from
 2 (select a.*, rownum as rn from
 3 (select owner, object_name, rowid from t_test1 order by owner, object_id) a
 4 where rownum <= 10)
 5 where rn >= 1;
 
OWNER OBJECT_NAME
------------------------------ ------------------------------
AFWOWNER AFWADAPTER
AFWOWNER AFWADAPTERFQN_PK
AFWOWNER AFWADAPTERCONFIGURATION
AFWOWNER AFWADAPTERCONFIGURATION_PK
AFWOWNER &nbs 




下载本文
显示全文
专题