本文分析並介紹 Oracle 中的分頁查找的方法。sql
Oracle 中的表,除了咱們建表時設計的各個字段,其實還有兩個字段(此處只介紹2個),分別是 ROWID(行標示符)和 ROWNUM(行號),即便咱們使用DESCRIBE命令查看錶的結構,也是看不到這兩個列的描述的,由於,他們實際上是隻在數據庫內部使用的,因此也一般稱他們爲僞列(pseudo column)。數據庫
下面咱們先建表並添加一些數據來驗證上面的說明。優化
建表:編碼
create table users( id integer primary key, name nvarchar2(20) )
插入數據:spa
insert into users(id,name) values(1,'tom'); insert into users(id,name) values(2,'cat'); insert into users(id,name) values(3,'bob'); insert into users(id,name) values(4,'anxpp'); insert into users(id,name) values(5,'ez'); insert into users(id,name) values(6,'lily');
使用describe命令查看錶結構:
能夠看到,確實只有建表時的兩個字段。
.net
但咱們能夠查詢的時候,查找到僞列的值:
設計
select rowid,rownum,id,name from users;
結果:code
這個 rowid 咱們通常用不到,Oracle 數據庫內部使用它來存儲行的物理位置,是一個 18 位的數字,採用 base-64 編碼。blog
而這個 rownum,咱們也正是使用它來進行分頁查詢的,它的值,就是表示的該行的行號。排序
對於分頁,咱們只要想辦法能夠查詢到從某一塊兒始行到終止行就能夠的,分頁的邏輯能夠放到程序裏面。
因而,咱們理所固然會想到以下語句查詢第 2 頁的數據(每頁2條數據,頁碼從 1 開始,因此起始行的行號爲 (頁碼-1) * 每頁長度 +1=3,終止行的行號爲 頁碼*每頁長度=4 )。
select * from users where rownum>=3 rownum <= 4;
哈哈!是否是發現沒有任何結果,緣由很簡單,Oracle機制就是這樣的:由於第一條數據行號爲1,不符合>=3的條件,因此第一行被去掉,以前的第二行變爲新的第一行(即這個行號不是寫死的,能夠理解爲是動態的),如此下去,一直到最後一行,條件始終無法知足,因此就一條數據也查不出來。
既然找到了緣由,解決方法也就很明顯了,咱們只要將行號查詢出來生成一個結果集,而後再從這個結果集中,選擇行號大於咱們設定的那個值就能夠了,上面的分頁查找正確的寫法應該是這樣:
select id,name from( select rownum rn,u.* from users u) ua where ua.rn between 3 and 4;
上面的語句還能夠優化:>= 不能用,可是 <= 是能夠的,咱們不須要在子查詢中將結果所有查出來,首先使用終止行篩選子查詢的結果,SQL以下:
select id,name from( select rownum rn,u.* from users u where rownum<=4) ua where ua.rn >= 3;
結果:
不少時候,咱們並非盲目的分頁查找的,二十按某一個或多個字段的升序或降序分頁,即包含 order by 語句的分頁查詢,咱們先看一下 order by 的查詢結果中 rownum 是怎樣的:
select rownum,id,name from users order by name;
結果:
能夠看到,咱們說行號徹底是動態的,也是不許確的,這時候的行號並非通過 order by 後新結果的增序行號。
但有了上面的嵌套查詢的經驗,這裏也能夠好好應用一下,怎麼作呢:先查找出排序好的結果集,而後應用上面的方法獲得最終結果,sql 以下:
select id,name from( (select rownum rn,uo.* from (select * from users u order by name) uo where rownum<=4)) ua where ua.rn>=3;
按照上面的結果,正確的分頁結果應該是 id 爲 2 和 5 的,看下結果:
OK,結果正確。
其實連表查詢之類的,也是差很少的,多點嵌套而已,掌握了原理,隨便分析一下就能寫出對應的 SQL 了,而編寫 SQL 時,咱們也得動動腦子,畢竟 SQL 也是由優劣之分的。
原文寫得很好能夠看下!