在Oracle中有一個很有趣的東西那就是rownum當你從某個表中查詢數據的時候返回的結果集中都會帶有rownum這個字段而且有時候也可以使用rownum進行一些條件查詢
在查詢中我們可以注意到類似於select xx from table where rownum < n(n>)這樣的查詢是有正確含義的而select xx from table where rownum = n這樣的查詢只在n=的時候成立select xx from table where rownum > n(n>)這樣的查詢只能得到一個空集另外select xx from table where rownum > 這個查詢會返回所有的記錄這是為什麼呢?原因就在於Oracle對rownum的處理上rownum是在得到結果集的時候產生的用於標記結果集中結果順序的一個字段這個字段被稱為偽數列也就是事實上不存在的一個數列它的特點是按順序標記而且是逐次遞加的換句話說就是只有有rownum=的記錄才可能有rownum=的記錄
讓我們回頭來分析一下在where中使用rownum作為查詢條件的情況在rownum取=或者rownum <= n (n>)的時候沒有問題那麼為什麼當條件為rownum = n或者rownum >= n時明明有數據卻只能得到一個空集呢?假設我們的查詢條件為rownum = 那麼在查詢出的第一條記錄的時候oracle標記此條記錄rownum為結果發現和rownum=的條件不符於是結果集為空寫到這裡我忽然有一個有趣的想法假如有一條查詢語句為select xxyy from table where zz > and rownum < 那麼在執行的時候是先按照zz>的條件查詢出一個結果集然後按照rownum取出前條返回?還是在按照zz>的條件先查詢然後有一個記錄就標記一個rownum到rownum<的時候就停止查詢?我覺得應該是後者也就是在執行語句的時候不是做full scan而是取夠數據就停止查詢要驗證這個想法應該很簡單找一個數據量非常大的表進行查詢就可以了可惜目前我沒有這樣的表
我們可以看出直接使用rownum是要受到限制的但是很容易遇到這樣的需求查出符合條件的第xx條到第xx條記錄比如頁面的分頁處理這個時候如何構造出適合自己的結果集?嗯牆邊那位說全取出來手工挑選的哥們可以拉出去了當然這樣做也是可以的但是前提是整個數據集的數據條數不多的情況下假如遇到上十萬百條的數據全部取出來的話用戶就不用干別的事情了這個時候用戶應該怎麼做呢?當然就是要用到我們介紹的rownum拉!rownum不是個偽數列麼好說我們現在把它弄成一個實在的字段就可以了具體做法就是利用子查詢在構建臨時表的時候把rownum也一起構造進去比如select xxyy from (select xxyyrownum as xyz from table where zz >) where xyz between and 這樣就可以了另外使用oracle提供的結果集處理函數minus也可以做到例如select xxyy from table where zz > and rownum < minus select xxyy from table where zz> and rownum <但是使用minus好像比使用子查詢更加消耗資源
和rownum相似oracle還提供了另外一個偽數列rowid不過rowid和rownum不同一般說來每一行數據對應的rowid是固定而且唯一的在這一行數據存入數據庫的時候就確定了可以利用rowid來查詢記錄而且通過rowid查詢記錄是查詢速度最快的查詢方法(這個我沒有試過另外要記住一個長度在位而且沒有太明顯規律的字符串是一個很困難的事情所以我個人認為利用rowid查詢記錄的實用性不是很大)rowid只有在表發生移動(比如表空間變化數據導入/導出以後)才會發生變化
From:http://tw.wingwit.com/Article/program/Oracle/201311/18298.html