oracle分页(一文看懂Oracle分页实现方案的三种方式)Oracle分页实现 闲来无事,整理下Oracle、mysql、mssql以及PG数据库的分页实现方式,大家可以简单做个对比,看下不同数据库在分页这块是怎么实现的。今天先介绍一下Oracle分页的实现方式。 oracle的分页一共有三种方式,但在Oracle中实现分页的方法主要是用ROWNUM关键字和用ROWID关键字两种。Rownum和Rowid是Oracle数据库所特有的,通过他们可以查询到指定行数范围内的数据记录。1、根据rowid来分 Oracle使用rowid数据类型存储行地址,rowid是物理存在的,实际存在的一个列,是一种数据类型。基于64为编码的18个字符来唯一标识的一条记录的物理位置的一个ID。而唯一标识出对应的存储的物理位置,类似hashcode值。 rowid可以分成两种,分别适于不同的对象:1)Physicalrowids:存储ordinarytable,clusteredtable,tablepartitionandsubpartition,indexe,indexpartitionandsubpartition2)Logicalrowids:存储IOT的行地址 另一种rowid类型叫universalrowed(UROWID),支持上述physicalrowid和logicalrowed,并且支持非oracletable,即支持所有类型的rowid,但COMPATIBLE必须在8。1或以上。 每个表在oracle内部都有一个ROWID伪列,它在所有sql中无法显示,不占存储空间;它用于从表中查询行的地址或者在where中进行参照,rowid伪列不存储在数据库中,它不是数据库数据,这是从database及table的逻辑结构来说的,事实上,在物理结构上,每行由一个或多个rowpieces组成,每个rowpiece的头部包含了这个piece的address,即rowid。从这个意义上来说,rowid还是占了磁盘空间的。 我们在创建表时,可以为列指定为rowid数据类型,但oracle并不保证列中的数据是合法的rowid值,必须由应用程序来保证,另外,类型为rowid的列需要6bytes存储数据 一般实现分页的过程如下: 1)获取数据物理地址:SELECTROWIDRID,tablenumberFROMtablenameORDERBYtablenumberDESC 2)取得最大页数:SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,tablenumberFROMtablenameORDERBYtablenumberDESC)WHEREROWNUMlt;xx 3)取得最小页数:SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,tablenumberFROMtablenameORDERBYtablenumberDESC)WHEREROWNUMlt;xx) 4)因为取得的页数都是物理地址,再根据物理地址,查询出具体数据currentPage:当前页数pageSize:每页显示几条SELECTFROMtablenameWHEREROWIDIN(SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,tablenumberFROMtablenameORDERBYtablenumberDESC)WHEREROWNUMlt;((currentPage1)pageSizepageSize))WHERERNgt;((currentPage1)pageSize))ORDERBYtablenumberDESC; 2、按分析函数ROWNUMBER()OVER()来分 语法格式:rownumber()over(partitionby分组列orderby排序列desc) oracle中的ROWNUMBER()OVER(partitionbycol1orderbycol2)表示根据col1分组,在分组内部根据col2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内是连续且唯一的) 一般实现分页的过程如下:currentPage:当前页数pageSize:每页显示几条SELECTFROM(SELECTT。,ROWNUMBER()OVER(ORDERBYtablenumberDESC)RKFROMtT)WHERERKlt;((currentPage1)pageSizepageSize)ANDRKgt;((currentPage1)pageSize); 3、根据rownum来分 rownum是伪列,是在获取查询结果集后再加上去的(获取一条记录加一个rownum)。对符合条件的结果添加一个从1开始的序列号 对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推,这个伪字段可以用于限制查询返回的总行数,且rownum不能以任何表的名称作为前缀。 一般实现分页的过程如下:currentPage:当前页数pageSize:每页显示几条SELECTFROM(SELECTT。,ROWNUMRNFROM(SELECTFROMtORDERBYtablenumberDESC)TWHEREROWNUMlt;((currentPage1)pageSizepageSize))WHERERNgt;((currentPage1)pageSize); 4、存储过程实现 这个存储过程主要是让大家看看分页的实现过程,可忽略1、开发一个包,在该包中,定义类型testcursor,是个游标createorreplacepackagetestpackageastypetestcursorisrefcursor;endtestpackage;2、开始编写分页的过程createorreplaceprocedurefenye(tableNameinvarchar2,表名pageSizeinnumber,一页显示记录数pageNowinnumber,当前页myrowsoutnumber,总记录数myPageCountoutnumber,总页数pcursorouttestpackage。testcursor返回的记录集)is定义部分定义sql语句字符串vsqlvarchar2(1000);定义两个整数vbeginnumber:(pageNow1)pageSize1;vendnumber:pageNowpageSize;begin执行部份vsql:39;selectfrom(selectt1。,rownumrnfrom(selectfrom39;tableName39;)t1whererownumlt;39;vend39;)whererngt;39;vbegin;把游标和sql关联openpcursorforvsql;计算myrows和myPageCount组织一个sqlvsql:39;selectcount()from39;tableName;执行sql,并把返回的值赋给myrows;executeimmediatevsqlintomyrows;计算myPageCountifmod(myrows,PageSize)0thenmyPageCount:myrowsPageSize;elsemyPageCount:myrowsPageSize1;endif;关闭游标closepcursor;end; 5、实例演示 5。1、环境准备createtablet(EMPNONUMBER(4)notnull,ENAMEVARCHAR2(10),JOBVARCHAR2(9),MGRNUMBER(4),HIREDATEDATE,SALNUMBER(7,2),COMMNUMBER(7,2),DEPTNONUMBER(2));altertabletaddconstraintPKEMPprimarykey(EMPNO)usingindex;INSERTINTOtVALUES(39;736939;,39;SMITH39;,39;CLERK39;,39;790239;,TODATE(39;1980121700:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;80039;,NULL,39;2039;);INSERTINTOtVALUES(39;749939;,39;ALLEN39;,39;SALESMAN39;,39;769839;,TODATE(39;1981022000:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;160039;,39;30039;,39;3039;);INSERTINTOtVALUES(39;752139;,39;WARD39;,39;SALESMAN39;,39;769839;,TODATE(39;1981022200:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;125039;,39;50039;,39;3039;);INSERTINTOtVALUES(39;756639;,39;JONES39;,39;MANAGER39;,39;783939;,TODATE(39;1981040200:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;297539;,NULL,39;2039;);INSERTINTOtVALUES(39;765439;,39;MARTIN39;,39;SALESMAN39;,39;769839;,TODATE(39;1981092800:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;125039;,39;140039;,39;3039;);INSERTINTOtVALUES(39;769839;,39;BLAKE39;,39;MANAGER39;,39;783939;,TODATE(39;1981050100:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;285039;,NULL,39;3039;);INSERTINTOtVALUES(39;778239;,39;CLARK39;,39;MANAGER39;,39;783939;,TODATE(39;1981060900:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;245039;,NULL,39;1039;);INSERTINTOtVALUES(39;778839;,39;SCOTT39;,39;ANALYST39;,39;756639;,TODATE(39;1987041900:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;300039;,NULL,39;2039;);INSERTINTOtVALUES(39;783939;,39;KING39;,39;PRESIDENT39;,NULL,TODATE(39;1981111700:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;500039;,NULL,39;1039;);INSERTINTOtVALUES(39;784439;,39;TURNER39;,39;SALESMAN39;,39;769839;,TODATE(39;1981090800:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;150039;,39;039;,39;3039;);INSERTINTOtVALUES(39;787639;,39;ADAMS39;,39;CLERK39;,39;778839;,TODATE(39;1987052300:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;110039;,NULL,39;2039;);INSERTINTOtVALUES(39;790039;,39;JAMES39;,39;CLERK39;,39;769839;,TODATE(39;1981120300:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;95039;,NULL,39;3039;);INSERTINTOtVALUES(39;790239;,39;FORD39;,39;ANALYST39;,39;756639;,TODATE(39;1981120300:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;300039;,NULL,39;2039;);INSERTINTOtVALUES(39;793439;,39;MILLER39;,39;CLERK39;,39;778239;,TODATE(39;1982012300:00:0039;,39;SYYYYMMDDHH24:MI:SS39;),39;130039;,NULL,39;1039;);commit; 5。2、根据rowid查询查询当前第一页,并显示5行数据(currentPage1,pagesize5)SELECTFROMtWHEREROWIDIN(SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,EMPNOFROMtORDERBYEMPNODESC)WHEREROWNUMlt;((11)55))每页显示几条WHERERNgt;((11)5))当前页数ORDERBYEMPNODESC;查询当前第二页,并显示6行数据(currentPage2,pagesize6)SELECTFROMtWHEREROWIDIN(SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,EMPNOFROMtORDERBYEMPNODESC)WHEREROWNUMlt;((21)66))每页显示几条WHERERNgt;((21)6))当前页数ORDERBYEMPNODESC; 5。3、根据分页函数查询查询当前第一页,并显示6行数据(currentPage1,pagesize6)SELECTFROM(SELECTT。,ROWNUMBER()OVER(ORDERBYtablenumberDESC)RKFROMtT)WHERERKlt;((11)55)每页显示几条ANDRKgt;((11)5);当前页数 5。4、根据分页函数查询查询当前第二页,并显示4行数据(currentPage2,pagesize4)SELECTFROM(SELECTT。,ROWNUMRNFROM(SELECTFROMtORDERBYempnoDESC)TWHEREROWNUMlt;((21)44))WHERERNgt;((21)4); 觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下