Oracle中rownum可以用来限制查询
具体用法:
1、返回查询集合中的第1行
select * from tableName where rownum = 1
2、返回查询集合中的第2行
错误示例:
select * from tableName where rownum = 2
正确示例:
select * from(select a.*,ROWNUM rownum_ from tableName a) where rownum_ = 2
提高效率可以这样写:
select * from(select a.*,ROWNUM rownum_ from tableName a ROWNUM <= 2) where rownum_ = 2
区别是内层查询先在内部过滤一波。
3、返回查询集合中的前5行
返回前5行,正确用法:
select * from tableName where rownum <= 5
或:
select * from tableName where rownum <= 5 AND rownum >= 1(0)
即加上>=1或写成>=0是没问题的
4、返回查询集合中的第3-5行
错误示例:
select * from tableName where rownum <= 5 AND rownum >= 3
这样返回为空
** rownum不可以用于>或>=,除非是后面跟0或1 **
正确示例:
select * from(select a.*,ROWNUM rownum_ from tableName a) where rownum_ >= 3 and rownum_ <= 5
或
select * from(select a.*,ROWNUM rownum_ from tableName a ROWNUM <= 5) where rownum_ >= 3
5、rownum分页查询
由第4条可以引出分页查询,配合rownum和子查询实现分页。
select * from(
select row_.*,rownum rownum_ from(
select * from tableName
) row_
)
where rownum_ >= 3 and rownum_ <= 5
三层嵌套查询,最内层查询是你的业务逻辑SQL,外面两层查询主要用来限制查询行数,可以提取出来套用,作为公共SQL拼装分页SQL。
乍一看,这和第4条【返回查询集合中的第3-5行】中的SQL查询效果一样,而且第4个还更简化。那为啥不用第4条的呢?
因为第4条的破坏了原始SQL(最初的业务逻辑SQL,不考虑任何其他只关注业务),在原来的SQL上加上了rownum,不太好。
而第5条,最内层查询是原始SQL,最纯净的,没有被破坏,只需要在自己的SQL外嵌套上分页SQL的模板即可,把模板提取出来,直接使用,对程序员来说是透明的,屏蔽了分页SQL,使程序员只关注业务实现,便于开发。
另一种写法:
select * from(
select row_.*,rownum rownum_ from(
select * from tableName
) row_ where rownum <= 5
)
where rownum_ >= 3
对比这两种写法,绝大多数的情况下,第2个查询的效率比第1个高得多。
这是由于CBO 优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第2个查询语句,第二层的查询条件where rownum <= 5就可以被Oracle推入到内层查询中,这样Oracle查询的结果一旦超过了rownum限制条件,就终止查询将结果返回了。即最多只查5条。
而第1个查询语句,由于查询条件存在于查询的第三层,而Oracle无法将第三层的查询条件推到最内层(即使推到最内层也没有意义,因为最内层查询不知道rownum_代表什么)。因此,对于第1个查询语句,Oracle最内层返回给中间层的是所有满足条件的数据,而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成,显然这个效率要比第2个查询低得多。
上面分析的查询不仅仅是针对单表的简单查询,对于最内层查询是复杂的多表联合查询或最内层查询包含排序的情况一样有效。