今天做項目時要實現分頁功能,以前只在mysql上弄過,oracle倒沒試過,但知道有這樣一個rownum這個東西。
但這個東西也不是那麼容易用的,還是有蠻多地方要注意的。它不是物理上存在的一列,而是oracle自己在結果集中進行添加的。
首先我們來看一下我們的表結構先:
我們新建一個表:
也就一個字段ID而已,這方便我們直接地看到結果。
我們先隨便插入幾條數據:
先弄進去5條吧。
我們直接來一個:
- select rownum,id from test;
我們看到結果:
很高興吧,都是一模一樣的,ronwum和ID是一樣的,方便我們看。
但結果看到的結果可能就會讓你鬱悶啦。
繼續下來,我們刪除幾條數據再插入幾條:
看到結果,我們是刪除了後面兩條,4,5這兩條記錄,而插入了8,9這兩條記錄。我們再來執行查詢:
- select rownum,id from test;
我們看到ID爲8,9的已經取代了之前的4,5得到了rownum爲4,5。這個說明了什麼,說明了rownum並不是物理存在的,如果是物理存在的那麼它肯定會隨着4,5的刪除而把rownum的4,5都刪除了,但它並沒有,而是把新插入的記錄的rownum作爲此值,這說明rownum肯定只是一個邏輯上的列,它有一個專門的名稱——僞列。
下面我們繼續插入數據,方便做下面的實驗:
如果我們需要取得前5條記錄,我們會怎麼做呢?我們看到前面的rownum是根據我們查出來的結果來進行賦值的,那麼我們就明白了,也許可以這樣:
- select rownum,id from test where rownum <= 5 order by id;
但很杯具的是,我們錯了,看看結果:
爲什麼錯呢?
原因就是rownum會在我們查詢出來結果還沒排序前就進行編號。由於是這個原因,我們只要加個字查詢就OK啦。
- select rownum,id from (select * from test order by id) where rownum <= 5;
我們看看結果:
現在沒問題了,已經按照rownum來排序了,也就是實現了我們的要求,查出前5個。
不要高興的太早,查前5個沒問題,那中間的記錄呢,第2到5個呢,或者大於5呢。我們來看看:
- select rownum,id from (select * from test order by id) where rownum >=1 and rownum <= 4;
看看結果:
這個有數據,而且正常,很好。
但不要高興,我們分頁一般不會只要第一條開始吧,如果要中間呢?我們看看:
- select rownum,id from (select * from test order by id) where rownum >= 2 and rownum <= 4;
這次不要大跌眼睛了:
杯具了吧。
爲什麼我們剛纔拿到的>=1時會有呢,而現在>=2沒有呢?
原因就是oracle在賦值rownum的時候會從1開始賦值,而當我們進行rownum >=1時,由於=1這個條件是成立的,所以它可以繼續取下一條rownum,繼續賦值到2,接連賦值下去。
而當我們用rownum >=2時,由於=2這個條件是不成立的,因爲當取到第一條rownum=1時,會把它丟棄,而當取到下一條時,rownum還是爲1,還是不滿足,一直這樣的循環,最後的結果就是沒數據可查出了。
但我們分頁確實要這樣要進行,怎麼辦呢?
其實也簡單,還是子查詢的方式,不是直接用rownum那我們把子查詢中的rownum命一個別名然後通過它來限定不就OK了。
我們看看:
- select rn,id from (select rownum as rn,id from (select * from test order by id) ) where rn >=2 and rn <= 4;
也許很多朋友看不明白是什麼意思,我們先看看結果:
很正常,沒問題吧。
但爲什麼這樣就沒問題呢?其實我們在上面的子查詢中,直接把rownum用rn作爲別名,它就被完全記錄下來了,這裏我們用它來作限定條件已經不關原來的rownum的事了。之所以要用兩個子查詢是因爲第一個排序需要作爲子查詢纔可以取到正確的rownum,纔可以定義別名。
相信看到這,大家都應該知道怎麼用oracle來實現分頁啦。