轉(zhuǎn)載請注明出處:http://blog.csdn.net/anxpp/article/details/51534006,謝謝!
本文分析并介紹Oracle中的分頁查找的方法。
Oracle中的表,除我們建表時設(shè)計的各個字段,其實還有兩個字段(此處只介紹2個),分別是ROWID(行標示符)和ROWNUM(行號),即便我們使用DESCRIBE命令查看表的結(jié)構(gòu),也是看不到這兩個列的描寫的,由于,他們實際上是只在數(shù)據(jù)庫內(nèi)部使用的,所以也通常稱他們?yōu)閭瘟校╬seudo column)。
下面我們先建表并添加1些數(shù)據(jù)來驗證上面的說明。
建表:
插入數(shù)據(jù):
使用describe命令查看表結(jié)構(gòu):
可以看到,確切只有建表時的兩個字段。
但我們可以查詢的時候,查找到偽列的值:
結(jié)果:
這個rowid我們1般用不到,Oracle數(shù)據(jù)庫內(nèi)部使用它來存儲行的物理位置,是1個18位的數(shù)字,采取base⑹4編碼。
而這個rownum,我們也正是使用它來進行分頁查詢的,它的值,就是表示的該行的行號。
對分頁,我們只要想辦法可以查詢到從某1起始行到終止行就能夠的,分頁的邏輯可以放到程序里面。
因而,我們天經(jīng)地義會想到以下語句查詢第2頁的數(shù)據(jù)(每頁2條數(shù)據(jù),頁碼從1開始,所以起始行的行號為 (頁碼⑴)*每頁長度+1=3,終止行的行號為 頁碼*每頁長度=4):
哈哈!是否是發(fā)現(xiàn)沒有任何結(jié)果,緣由很簡單,Oracle機制就是這樣的:由于第1條數(shù)據(jù)行號為1,不符合>=3的條件,所以第1行被去掉,之前的第2行變成新的第1行(即這個行號不是寫死的,可以理解為是動態(tài)的),如此下去,1直到最后1行,條件始終沒法滿足,所以就1條數(shù)據(jù)也查不出來。
既然找到了緣由,解決方法也就很明顯了,我們只要將行號查詢出來生成1個結(jié)果集,然后再從這個結(jié)果集中,選擇行號大于我們設(shè)定的那個值就能夠了,上面的分頁查找正確的寫法應(yīng)當(dāng)是這樣:
上面的語句還可以優(yōu)化:>=不能用,但是<=是可以的,我們不需要在子查詢中將結(jié)果全部查出來,首先使用終止行挑選子查詢的結(jié)果,SQL以下:
結(jié)果:
很多時候,我們其實不是盲目的分頁查找的,210按某1個或多個字段的升序或降序分頁,即包括 order by 語句的分頁查詢,我們先看1下 order by 的查詢結(jié)果中rownum是怎樣的:
結(jié)果:
可以看到,我們說行號完全是動態(tài)的,也是不準確的,這時候候的行號其實不是經(jīng)過 order by 后新結(jié)果的增序行號。
但有了上面的嵌套查詢的經(jīng)驗,這里也能夠好好利用1下,怎樣做呢:先查找出排序好的結(jié)果集,然后利用上面的方法得到終究結(jié)果,sql以下:
依照上面的結(jié)果,正確的分頁結(jié)果應(yīng)當(dāng)是id為2和5的,看下結(jié)果:
OK,結(jié)果正確。
其實連表查詢之類的,也是差不多的,多點嵌套而已,掌握了原理,隨意分析1下就可以寫出對應(yīng)的SQL了,而編寫SQL時,我們也得動動頭腦,畢竟SQL也是由優(yōu)劣之分的。