oracle中的區間查詢(類似mysql中的limit)
那麼Oracle中有limit嗎,答案是沒有。oracle中可以通過rownumber
Oracle使用rownum的關鍵字來實現這種查詢:
首先我們假設有一個地域資訊表area,其表結構如下圖所示:
表中的資料如下圖所示(select * from area語句得到的結果):
1)查詢表中的前8條記錄
select * from area where rownum <= 8
查詢結果如下:
2)查詢第2到第8條記錄
對於這種形式的查詢,oracle不像mysql那麼方便,它必須使用子查詢或者是集合操作來實現。我們可以使用以下3種方式可以實現:
A: select id,province,city,district from (select id,province,city,district,rownum as num from area) where num between 2 and 8;
首先根據select id,province,city,district,rownum as num from area得到一個臨時表,這個臨時表中有一個rownum列(一個偽列,類似與rowid,但又不同於rowid,因為rowid是物理存在的一個列,也就是說Oracle資料庫中任何一個表都有一個rowid列,而rownum不是物理存在的),然後在臨時表中來查詢。
B: select * from area where rownum <= 8 minus select * from area where rownum < 2;
使用集合減運算子minus,該操作返回在第一個select中出現而不在第二個select中出現的記錄。
C: select id,province,city,district from (select id,province,city,district,rownum as num from area) where num >=2
intersect
select * from area where rownum <= 8;
使用集合交運算子intersect,這裡繞了一個彎(不過這個彎實現了rownum大於某個數的查詢),它是首先利用A的方式查詢得到所有rownum大於2的記錄,然後再與rownum小於等於8的記錄集合做交運算。三種操作得到的結果一樣,如下圖所示:
3)rownum需要注意的問題
[1] rownum不支援以下方式的查詢
a: select * from area where rownum > 2;
b: select * from area where rownum = n; –where n is a integer number lager than 1
注:rownum只支援select * from area where rownum =1的查詢。Oracle的官方文件說明如下:
Conditions testing for ROWNUM values greater than a positive integer are always false.
For example, this query returns no rows:
SELECT * FROM employees
WHERE ROWNUM > 1;
The first row fetched is assigned a ROWNUM of 1 and makes the condition false. The
second row to be fetched is now the first row and is also assigned a ROWNUM of 1 and
makes the condition false. All rows subsequently fail to satisfy the condition, so no
rows are returned.
因為rownum是根據查詢的結果集來對記錄進行編號,所以當你查詢rownum大於2的記錄時會得到一個空的結果集。因為當oracle查詢得到第1條記錄時,發現rownum為1不滿足條件,然後就繼續查詢第2條記錄,但此時第2條記錄又被編號為1(也即rownum變為1),所以查詢得到的始終是rownum=1,因此無法滿足約束,最終查詢的結果集為空。
[2] rownum的排序查詢問題
Rownum的排序查詢是根據表中資料的初始順序來進行的。Oracle官方文件中說明如下:
If an ORDER BY clause follows ROWNUM in the same query, then the rows will be
reordered by the ORDER BY clause. The results can vary depending on the way the
rows are accessed. For example, if the ORDER BY clause causes Oracle to use an index
to access the data, then Oracle may retrieve the rows in a different order than without
the index.
例如:select * from area where rownum <= 8 order by district;
其結果如下圖所示:
發現沒有,它只對area表中的前8條記錄進行排序。那麼,如果我要取表中的前8條記錄並且要求是全表有序,那怎麼辦呢?還是老辦法,使用子查詢。我們可以使用以下語句得到:
select * from (select * from area order by district)
where rownum <= 8;
查詢的結果如下圖所示:
結束語:
Oracle中的rownum與mysql的limit實現的功能相同,但沒有mysql來的容易,它一般通過一個子查詢來實現。mysql的易用性也是它能夠縱橫開源資料庫的原因,它不像postgresql那樣的學院派,它的那種簡單易用性或許在大型軟體專案的開發中值得借鑑。最近聽說sql server 2008也實現了limit的查詢,不過還沒去試過,Oracle在這方面也要加油啊,使用者容易使用才是王道