Oracle分页以及与MySql的比较

时间:2022-01-04 14:54:46

这是本新人的第一篇博客,目的是想把刚总结的知识记录下来,并与大家一起讨论分享。
这第一篇博客是我觉得网上其他大神写的技术对于新人可能难于接受,就试着根据自己的总结希望用简单的方法说说自己的见解,写的不好请包涵!
而且这里语句统一小写,小写的英文更容易看懂单词的含义嘛!
如果跟我一样是新人要学习分页,首先要知道这里的分页并不是我们生活中那种分页,有下一页,上一页那样可以点的;只是筛选出所有记录中的某一段记录作为查询的一页。具体的实现是还是靠PL/SQL后面的知识,慢慢来;

    进入主题吧,首先讲讲MySql的分页,MySql对分页有很方便的语句,就是limit。
格式是limit num1,num2;意思是检索从第num1条到第num2条的记录,如果是检索前几条记录可以省去num1,比如前十条记录limit 10;

但是oracle却没这么简单了,oracle的分页只要涉及的是ROWNUM,从英文可以看出他代表的意思吧,就是行编号;oracle实现分页的方法从整体上来看,就只要两种(目前就我在网上查到的),在这里我把他称作集合方法子查询方法

集合方法

:数学我们都学过集合吧,并集,交集….这些oracle都有实现关键字,这里我用减集合举例(其它的原理一样,大家百度吧):
我们要检索出第10~20条的记录,就先查询前20条再减去前10条

select * from tb_name where rownum<=20 minus select * from tb_name where rownum<10;

这里主要用到的是minus,是减的意思。用前面查询的前20条记录减去后面查询的前10条记录。

子查询方法

这个方法的思想是让rownum成为表的一个列,这样就不会有rownum不能接大于号的限制了,首先我们创建个含rownum的临时表子查询:

select  t.*  rownum as num from tb_name as t;

这里as是取别名的意思,大家都懂,as可以省略;但我要大家注意的不是这个,本人亲测如果不给rownum取别名的话,是无法实现我们的最终目的的,大家可以试试,因为rownum作为一个oracle的关键…就是有不能接大于的限制。这里我们已经有了一个临时表,除了我们要分页的字段外还有个num字段。然后这样做:

select * from  (...) where num between 10 and 20;
这里的where后面已经可以写让num大于某值的条件,只是在这里between更加方便。括号里代表的是上面的子查询。
这里还有个需要注意的,此时外层的select是包含了num字段的,所以如果不需要num字段,就必须列出所有其他字段了

到此我们已经完成了子查询方法完成分页的基本方法。


排序和分页

但是实际中有些特殊情况我们还需要特别注意,做些额外的小修改。
排序与分页同时实现的时候,

    select * from tb_name where rownum<=10 order by id;

在上面这句中是先检索出这10条记录,再把这10条记录进行排序,第11条后面记录不排序。如果需要先将表所有记录排序后分页,则需要将排序语句作为子查询先进行

 select * from (select * from tb_name order by id) where rownum<=10

对rownum的理解

,oracle已经规定了,它有两种表示是不允许的:

 1. 不能接大于和大于等于号,如rownum>n,rownum>=n
2. 不能接等于号,如rownum=n;

如果想突破这种限制上面已经有写了,就是作为一个字段名,改名加入到表中,但这不会觉得它已经变味了吗,已经失去了他原有的意义了……


还有个问题我没弄懂的,就是效率问题,看了篇别人的帖子
http://blog.sina.com.cn/s/blog_8604ca230100vro9.html
他说到了我的第二种方法是效率最高的,而且他的文章没提到第一种方法,我在pl/sql development上测试了一下,

  • 在小数据(我用的1000条)时,子查询方法效率高于集合的方法。
  • 在数据较大(我用的是6W条记录)时,减集合的方法明显优于子函数的方法。

而且小数据的差别也不是很大,就是十几毫秒,数据量大点就是接近十秒的差距了。
希望大家一起讨论,有答案的大神们能给我及一起学习的人一个解答,谢谢!


这是本新人第一篇博客,排版表达都是即兴的。小小总结下学习的成果,难免包含了个人的偏见,如果有错误也望各位大神提出来,大家共同进步,谢谢!