只要做web開發(fā)抹凳,幾乎沒有不需要分頁查詢的井辜,在oracle中修壕,rownum就是用來進(jìn)行處理分頁的钉凌。
rownum是oracle對結(jié)果集返回的一個偽列,也就是說是先查詢完結(jié)果之后再加上的一個虛列帐偎,相當(dāng)于對符合條件的結(jié)果的一個序列號逐纬。如果有結(jié)果的話,rownum偽列產(chǎn)生的序號是按照數(shù)據(jù)被查詢出來的順序添加上去的削樊, rownum總是從1開始豁生,依次加1,先看個例子漫贞。
select rownum,u.* from t_user u
可以看到甸箱,rownum依次顯示了。我們需要查找前10條數(shù)據(jù)
select rownum,u.* from t_user u where rownum <= 10
數(shù)據(jù)正常查找出來迅脐,沒有問題芍殖。如果我們查詢結(jié)果中有排序呢,看看結(jié)果如何
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豌骏;
可以看到數(shù)據(jù)沒有問題龟梦,換成下面的語句
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肯适;
可以看到变秦,按照創(chuàng)建時間排序查詢前10條有問題了成榜,但是看第二條執(zhí)行結(jié)果框舔,創(chuàng)建時間最近的應(yīng)該是chenz.ccsd而不是第一條中的43573830。為什么會這樣呢赎婚?
這是因?yàn)镺RACLE內(nèi)部的查詢優(yōu)化器和索引搞的鬼刘绣。
當(dāng)一條語句交給查詢優(yōu)化器處理時,會有兩種情況:
一種如果排序列上有索引的話挣输,則借助索引去查詢數(shù)據(jù)纬凤,這樣讀取出來的數(shù)據(jù)是有序的,然后為排序后的數(shù)據(jù)從第一行到最后一行賦予rownum值撩嚼;
另一種排序列上沒有沒有索引的話停士,則會先進(jìn)行全表掃描依次讀取數(shù)據(jù),然后為數(shù)據(jù)賦予rownum值完丽,再進(jìn)行排序恋技,此時所選取的數(shù)據(jù)就不是進(jìn)行排序的了。
上面語句中c_id是有索引的逻族,而c_createdate是沒有建立索引的蜻底。
由于排序列上不一定要有索引,所以在使用rownum分頁時聘鳞,需要多加一層查詢薄辅,以保證rownum的連續(xù)性。