爱是王道 发表于 2018-9-14 10:51:43

oracle-rownum的理解

  rownum是什么?
  rownum是一个伪列,在表中不是真实存在的
  rownum是oracle从数据文件或者缓冲区读取数据的一个顺序
  如果想得到一个表中第二行的数据,按照select * from test where rownum=1;这个查询,查询得到的数据不是正确的,而且只能是在=1时能查出数据,在等于其他值的时候是查不出任何数据的
  rownum只能跟小于等于,不能跟大于,如果要大于需要和小于同时使用
  rownum工作原理:
  由于表中没有行号,因此是不能查询到第几行的数据的
  首先,标准的 SQL 的解析顺序为:
  (1).FROM 子句, 组装来自不同数据源的数据
  (2).WHERE 子句, 基于指定的条件对记录进行筛选
  (3).GROUP BY 子句, 将数据划分为多个分组
  (4).使用聚合函数进行计算
  (5).使用 HAVING 子句筛选分组
  (6).计算所有的表达式
  (7).使用 ORDER BY 对结果集进行排序
  (8).最后是select ,执行查询
  rownum是在执行的查询语句执行谓词之后且在完成排序或者簇集之前赋予值的,在分配后值加1
  既在有select 、from 、where 、group by 、having、order by 的查询中,先后执行顺序是:
  from/where -> rownum(这个是从from/where结果中分配给每个行rownum并且增加1) -> select -> group by -> having -> order by
  因为oracle会把执行查询的得到的第一个符合条件的结果rownum加1,而不符合条件的会仍掉,如果符合条件会在后面+1,而执行select * from test where rownum>1;而条件是>1,而1不是大于1的,就依次推全表扫表没有符合条件的值,所以这句话永远都查询不出来结果的!!!!
  执行select * from test where rownum>1;这句话的执行计划:
SYS@u01>select * from test where rownum>1;  
no rows selected
  
Elapsed: 00:00:00.08
  
Execution Plan
  
----------------------------------------------------------
  
Plan hash value: 2091529335
  
----------------------------------------------------------------------------

  
|>  
----------------------------------------------------------------------------
  
|   0 | SELECT STATEMENT    |      | 69115 |    13M|   294   (1)| 00:00:04 |
  
|   1 |COUNT          |      |       |       |      |      |
  
|*2 |   FILTER      |      |       |       |      |      |
  
|   3 |    TABLE ACCESS FULL| TEST | 69115 |    13M|   294   (1)| 00:00:04 |
  
----------------------------------------------------------------------------

  
Predicate Information (identified by operation>  
---------------------------------------------------
  
2 - filter(ROWNUM>1)
  
Note
  
-----
  
- dynamic sampling used for this statement (level=2)
  
Statistics
  
----------------------------------------------------------
  
49recursive calls
  
0db block gets
  
1267consistent gets
  
1363physical reads

  
0redo>  
1343bytes sent via SQL*Net to client
  
512bytes received via SQL*Net from client
  
1SQL*Net roundtrips to/from client
  
4sorts (memory)
  
0sorts (disk)
  
0rows processed
  首先是TABLE ACCESS FULL.....
  因为是先得到符合条件的行,再为符合条件的行对其赋予rownum,在得到的行一次+1赋值,所以查出来的是1.2.3.....n.
  例如对于emp表如果想知道薪水排在前5行的人的信息,执行:select * from emp where rownum5的去掉前5行数据(这里使用的rn别名,是剩下10行的那个rownum,为了不与最外层的那个rownum冲突),然后得到的就是中间的排序后第5到10行数据
  为了好理解,查询弄多个别名:
SCOTT@u01>select rownum,rn,re FROM (Select rownum rn ,b.* from (select rownum re,e.* from emp e order by ename desc) b where rownum5;  
ROWNUM   RN         RE
  
---------- ---------- ----------
  
1      6          5
  
2      7          9
  
3      8          4
  
4      9         12
  
Elapsed: 00:00:00.03
  
SCOTT@u01>
  set autot on;
  既显示查询的结果,也显示执行计划、执行路径、统计信息
  set autot trace
  不显示查询的结果,只显示执行计划、执行路径、统计信息


页: [1]
查看完整版本: oracle-rownum的理解