天天看點

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;           

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