oracle分页(一文看懂Oracle分页实现方案的三种方式)-飞外

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称为通用行id(uro wid),支持上述物理rowid和逻辑行id,也支持非oracle表,即所有类型的rowid,但兼容的必须是8.1以上版本。

每个表在oracle中都有一个ROWID伪列,不能在所有sql中显示,不占用存储空空间;它用于从表中查询行的地址或在where中进行引用。rowid伪列不存储在数据库中,它不是数据库数据,是基于数据库和表的逻辑结构。其实物理上每一行都是由一个或多个行片组成的,每个行片的头都包含了这个片的地址,也就是rowid。从这个意义上说,rowid仍然占据着磁盘/[/k0/

创建表时,我们可以为列指定rowid数据类型,但oracle不保证列中的数据是合法的rowid值,这必须由应用程序来保证。另外,rowid类型的列需要6个字节来存储数据。

一般的分页过程如下:

1)获取数据的物理地址:select rowid rid,table _ name中的表号order by Table num desc 2)获取 页数:select rownum rn,rid from (select rowid rid,num from Table _ name中的号order by Table num desc)where rownum 3)获取最小页数:select rid from (select rownumrn,rid from (select rowid rid,Table from table _ name中的表号order by Table num desc)where rownum 4)由于获取的页码都是物理地址,所以可以根据物理地址查询具体数据

--currentPage:当前页数--pageSize:每页显示几条SELECT*FROMtable_nameWHEREROWIDIN(SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,tablenumberFROMtable_nameORDERBYtablenumberDESC)WHEREROWNUM((currentPage-1)*pageSize))ORDERBYtablenumberDESC;

2.根据分析函数ROW_NUMBER()除以()

语法:row_number() over(通过对列排序按列顺序分组进行分区desc)

oracle中的row _ number()over(partition by col1 order by col2)表示按col 1分组,分组内按col 2排序,该函数计算的值表示每个组内的有序序号(组是连续的,唯一的)。

一般的分页过程如下:

--currentPage:当前页数--pageSize:每页显示几条SELECT*FROM(SELECTT.*,ROW_NUMBER()OVER(ORDERBYtablenumberDESC)RKFROMtT)WHERERK((currentPage-1)*pageSize);

3.根据rownum划分

Rownum是伪列,在获取查询结果集后添加(获取一条记录,添加一个rownum)。向合格结果添加一个从1开始的序列号。

对于rownum,它是oracle系统分配给查询返回的行的序列号。返回的 行被赋予1,过程如下:

--currentPage:当前页数--pageSize:每页显示几条SELECT*FROM(SELECTT.*,ROWNUMRNFROM(SELECT*FROMtORDERBYtablenumberDESC)TWHEREROWNUM((currentPage-1)*pageSize);

4.存储过程的实现

这个存储过程主要是给大家展示分页的实现过程,可以忽略。

--1、开发一个包,在该包中,定义类型test_cursor,是个游标createorreplacepackagetestpackageastypetest_cursorisrefcursor;endtestpackage;--2、开始编写分页的过程createorreplaceprocedurefenye(tableNameinvarchar2,--表名pageSizeinnumber,--一页显示记录数pageNowinnumber,--当前页myrowsoutnumber,--总记录数myPageCountoutnumber,--总页数p_cursorouttestpackage.test_cursor--返回的记录集)is--定义部分--定义sql语句字符串v_sqlvarchar2(1000);--定义两个整数v_beginnumb(道不同不相为谋什么意思?道不同不相为谋是一个汉语成语,意思是有不同志向的人,就不能在一起谋划。比喻意见或志趣不同的人就无法共事。出自孔子《论语·卫灵公》:“道不同,不相为谋。”)er:=(pageNow-1)*pageSize+1;v_endnumber:=pageNow*pageSize;begin--执行部份v_sql:='select*from(selectt1.*,rownumrnfrom(select*from'||tableName||')t1whererownum='||v_begin;--把游标和sql关联openp_cursorforv_sql;--计算myrows和myPageCount--组织一个sqlv_sql:='selectcount(*)from'||tableName;--执行sql,并把返回的值赋给myrows;executeimmediatev_sqlintomyrows;--计算myPageCountifmod(myrows,PageSize)=0thenmyPageCount:=myrows/PageSize;elsemyPageCount:=myrows/PageSize+1;endif;--关闭游标closep_cursor;end;

5.示例演示

5.1.环境准备

createtablet(EMPNONUMBER(4)notnull,ENAMEVARCHAR2(10),JOBVARCHAR2(9),MGRNUMBER(4),HIREDATEDATE,SALNUMBER(7,2),COMMNUMBER(7,2),DEPTNONUMBER(2));altertabletaddconstraintPK_EMPprimarykey(EMPNO)usingindex;INSERTINTOtVALUES('7369',' ITH','CLERK','7902',TO_DATE('1980-12-1700:00:00','SYYYY-MM-DDHH24:MI:SS'),'800',NULL,'20');INSERTINTOtVALUES('7499','ALLEN','SALE AN','7698',TO_DATE('1981-02-2000:00:00','SYYYY-MM-DDHH24:MI:SS'),'1600','300','30');INSERTINTOtVALUES('7521','WARD','SALE AN','7698',TO_DATE('1981-02-2200:00:00','SYYYY-MM-DDHH24:MI:SS'),'1250','500','30');INSERTINTOtVALUES('7566','JONES','MANAGER','7839',TO_DATE('1981-04-0200:00:00','SYYYY-MM-DDHH24:MI:SS'),'2975',NULL,'20');INSERTINTOtVALUES('7654','MARTIN','SALE AN','7698',TO_DATE('1981-09-2800:00:00','SYYYY-MM-DDHH24:MI:SS'),'1250','1400','30');INSERTINTOtVALUES('7698','BLAKE','MANAGER','7839',TO_DATE('1981-05-0100:00:00','SYYYY-MM-DDHH24:MI:SS'),'2850',NULL,'30');INSERTINTOtVALUES('7782','CLARK','MANAGER','7839',TO_DATE('1981-06-0900:00:00','SYYYY-MM-DDHH24:MI:SS'),'2450',NULL,'10');INSERTINTOtVALUES('7788','SCOTT','ANA ST','7566',TO_DATE('1987-04-1900:00:00','SYYYY-MM-DDHH24:MI:SS'),'3000',NULL,'20');INSERTINTOtVALUES('7839','KING','PRESIDENT',NULL,TO_DATE('1981-11-1700:00:00','SYYYY-MM-DDHH24:MI:SS'),'5000',NULL,'10');INSERTINTOtVALUES('7844','TURNER','SALE AN','7698',TO_DATE('1981-09-0800:00:00','SYYYY-MM-DDHH24:MI:SS'),'1500','0','30');INSERTINTOtVALUES('7876','ADAMS','CLERK','7788',TO_DATE('1987-05-2300:00:00','SYYYY-MM-DDHH24:MI:SS'),'1100',NULL,'20');INSERTINTOtVALUES('7900','JAMES','CLERK','7698',TO_DATE('1981-12-0300:00:00','SYYYY-MM-DDHH24:MI:SS'),'950',NULL,'30');INSERTINTOtVALUES('7902','FORD','ANA ST','7566',TO_DATE('1981-12-0300:00:00','SYYYY-MM-DDHH24:MI:SS'),'3000',NULL,'20');INSERTINTOtVALUES('7934','MILLER','CLERK','7782',TO_DATE('1982-01-2300:00:00','SYYYY-MM-DDHH24:MI:SS'),'1300',NULL,'10');commit;

5.2.根据rowid查询

--查询当前 页,并显示5行数据(currentPage=1,pagesize=5)SELECT*FROMtWHEREROWIDIN(SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,EMPNOFROMtORDERBYEMPNODESC)WHEREROWNUM((1-1)*5))--当前页数ORDERBYEMPNODESC;--查询当前,并显示6行数据(currentPage=2,pagesize=6)SELECT*FROMtWHEREROWIDIN(SELECTRIDFROM(SELECTROWNUMRN,RIDFROM(SELECTROWIDRID,EMPNOFROMtORDERBYEMPNODESC)WHEREROWNUM((2-1)*6))--当前页数ORDERBYEMPNODESC;

5.3.根据分页功能进行查询

--查询当前 页,并显示6行数据(currentPage=1,pagesize=6)SELECT*FROM(SELECTT.*,ROW_NUMBER()OVER(ORDERBYtablenumberDESC)RKFROMtT)WHERERK((1-1)*5);--当前页数

5.4.根据分页功能进行查询

--查询当前,并显示4行数据(currentPage=2,pagesize=4)SELECT*FROM(SELECTT.*,ROWNUMRNFROM(SELECT*FROMtORDERBYempnoDESC)TWHEREROWNUM((2-1)*4);

觉得有用的朋友帮忙转发一下吧!后面会分享更多关于devops和DBA的内容,感兴趣的朋友可以关注一下~