Oracle中的分頁查詢~~~ROWNUM(行號)

Oracle中的表,除了我們建表時設計的各個字段,其實還有兩個字段(此處只介紹2個),分別是ROWID(行標示符)和ROWNUM(行號)。即使我們使用DESCRIBE命令查看錶的結構,也無法看到這兩個列的描述,因爲它們其實是隻在數據庫內部使用的,所以也通常稱它們爲僞列(pseudo column)。
建一個只有兩個字段(id,col)的表。使用describe命令查看錶結構,可以看到確實只有建表時的兩個字段。但我們可以查詢的時候,可以查找到僞列的值。

select rowid,rownum,id,col from table;

這個rowid我們一般用不到,Oracle數據庫內部使用它來存儲行的物理位置,是一個18位的數字,採用base-64編碼。而這個rownum,我們正是用它來進行分頁查詢的,它的值,就是表示的該行的行號。
對於分頁查詢,我們只要想辦法可以查詢到從某一起始行到終止行就可以的,分頁的邏輯可以放到程序裏面。於是,我們理所當然會想到如下語句查詢第2頁的數據(每頁2條數據,頁碼從1開始,所以起始行的行號爲 (頁碼-1)*每頁長度+1=3,終止行的行號爲 頁碼*每頁長度=4):

select * from table where rownum>=3 rownum <= 4;

出人意料,沒有任何結果。原因很簡單,Oracle機制就是這樣的:因爲第一條數據行號爲1,不符合>=3的條件,所以第一行被去掉,之前的第二行變爲新的第一行(即這個行號不是寫死的,可以理解爲是動態的),如此下去,一直到最後一行,條件始終沒法滿足,所以就一條數據也查不出來。
對症下藥,要想解決這個問題,我們只要將行號查詢出來生成一個結果集,然後再從這個結果集中,選擇行號大於我們設定的那個值就可以了,上面的分頁查找正確的寫法應該是這樣:

select id,col from(
select rownum rn,u.* from table u) ua
where ua.rn between 3 and 4;

上面的語句還可以優化:雖然不能用">=",但"<="卻可以用。爲提高查詢效率,我們可以使用終止行篩選子查詢的結果,SQL如下:

select id,col from(
select rownum rn,u.* from table u where rownum<=4) ua
where ua.rn >= 3;

很多時候,我們並不是盲目的分頁查找的,而是按某一個或多個字段的升序或降序分頁,即包含 order by 語句的分頁查詢,我們先看一下 order by 的查詢結果中rownum是怎樣的:

select rownum,id,col from table order by col;

結果,這時候的行號並不是經過 order by 後結果的增序行號。
但有了上面的嵌套查詢的經驗,這裏也可以好好應用一下,怎麼做呢:先查找出排序好的結果集,然後應用上面的方法得到最終結果,sql如下:

select id,col from(
select rownum rn,uo.* from
(select * from table order by col) uo
where rownum<=4 ) ua
where ua.rn>=3;

分頁效果的實現,思路有三種:

其一:純JS實現分頁。一次性查詢記錄並加載到html的table中。然後通過選擇性地顯示某些行來達到分頁顯示的目的。這是一種僞分頁,障眼法而已。只能用於數據少的情況下。一旦數據多了,十幾萬條數據加載到html中會變得很慢。而且不實時,一次加載完後數據就寫死在頁面了,若數據庫中有變化,瀏覽器端顯示的仍是上次加載過來的數據。

其二:一次查詢,分批顯示。
就是說,我們可以執行一個數據庫查詢操作,得到結果集rs。然後,通過指針的移動來顯示當前頁面的記錄。這樣,就可以以 rs.absolute(當前頁面號*每頁記錄數)定位到當前頁的第一條記錄,然後通過while循環顯示n條記錄(n爲每頁顯示記錄數)。在跳頁時,只需修改currentPage,即可在重定位到下一頁時把當前頁面號改掉,重新定位記錄指針,通過while遍歷顯示n條記錄。與JS選擇性顯示不同,這裏是選擇性遍歷。與JS分頁不同的是,這裏分頁每次跳頁修改的是遍歷的指針,每次跳頁都要進行一次全面查詢。同樣地,不適合大數據量查詢。這裏比JS分頁優化的地方在於——實時性。每次跳頁都會查詢一次數據庫,保證數據的實時性。

其三:在服務端分頁。跳到第n頁才查詢、顯示第n頁內容。要點就是根據客戶端表格的“頁面”計算出數據庫要查詢的當前頁面的第一條記錄的位置。優點:實時性:跳頁才查詢。數據量小:只加載當前頁的記錄進行顯示。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章