只要做web開發,幾乎沒有不需要分頁查詢的,在oracle中,rownum就是用來進行處理分頁的。
1.rownum是oracle對結果集返回的一個偽列,也就是說是先查詢完結果之后再加上的一個虛列,相當於對符合條件的結果的一個序列號。如果有結果的話,rownum偽列產生的序號是按
照數據被查詢出來的順序添加上去的, rownum總是從1開始,依次加1。
select rownum,u.* from t_user u
可以看到,rownum按序顯示了。我們需要查找前10條數據
select rownum,u.* from t_user u where rownum <= 10
數據正常查找出來,沒有問題。如果我們查詢結果中有排序呢,看看結果如何
select rownum,u.* from t_user u where rownum <= 10 order by u.c_id desc;
select rownum,u.* from t_user u order by u.c_id desc;
(第一條語句執行結果)
(第二條語句執行結果)
可以看到數據沒有問題,換成下面的語句
select rownum,u.* from t_user u where rownum <= 10 order by u.c_createdate desc;
select rownum,u.* from t_user u order by u.c_createdate desc;
(第一條語句執行結果)
(第二條語句執行結果)
可以看到,按照創建時間排序查詢前10條有問題了,但是看第二條執行結果,創建時間最近的應該是chenz.ccsd而不是第一條中的43573830。為什么會這樣呢?
這是因為ORACLE內部的查詢優化器和索引搞的鬼。
當一條語句交給查詢優化器處理時,會有兩種情況:
一種如果排序列上有索引的話,則借助索引去查詢數據,這樣讀取出來的數據是有序的,然后為排序后的數據從第一行到最后一行賦予rownum值;
另一種排序列上沒有沒有索引的話,則會先進行全表掃描依次讀取數據,然后為數據賦予rownum值,再進行排序,此時所選取的數據就不是進行排序的了。
上面語句中c_id是有索引的,而c_createdate是沒有建立索引的。
由於排序列上不一定要有索引,所以在使用rownum分頁時,需要多加一層查詢,以保證rownum的連續性。