Oracle數據庫中的分頁--rownum


1. 介紹

當我們在做查詢時,經常會遇到如查詢限定行數或分頁查詢的需求,MySQL中可以使用LIMIT子句完成,在MSSQL中可以使用TOP子句完成,那么在Oracle中,我們如何實現呢?

Oracle提供了一個rownum的偽列,它會根據返回記錄生成一個序列化的數字。

rownum和rowid都是偽列,但是兩者的根本是不同的。rownum是根據SQL查詢出的結果給每行分配一個邏輯編號,所以SQL不同也就會導致最終rownum不同;rowid是物理結構上的,在每條記錄INSERT到數據庫中時,都會有一個唯一的物理記錄。

2. 限定查詢行數

如果希望限定查詢結果集的前幾條數據,通過ROWNUM可以輕松實現。

示例:

-- 查找前三條員工的記錄 SELECT * FROM employee WHERE rownum <= 3;

3. 分頁查詢

在數據庫應用系統中,我們會經常使用到分頁功能,如每頁顯示5條記錄,查詢第2頁內容該如何查詢呢?

SELECT * FROM employee WHERE rownum > 5 AND rownum <= 10;

上面的SQL語句是否能查詢出我們想要的結果呢?

當執行該SQL就會發現,顯示出來的結果要讓你失望了:查不出一條記錄,即使表中有20條記錄。問題是出在哪呢?

因為rownum是對結果集加的一個偽列(即先查到結果集之后再加上去的一個列),簡單的說rownum是對符合條件結果集添加的序列號。它總是從1開始排起的,所以選出的結果中不可能沒有1,而有其他大於1的值。

rownum > 5 AND rownum <= 10 查詢不到記錄,因為如果第一條的 rownum = 1,不滿足條件被去掉,第二條的rownum又成了1,繼續判斷,所以永遠沒有滿足條件的記錄。

任何時候想把 rownum = 1 這條記錄拋棄是不對的,它在結果集中是不可或缺的,少了rownum=1 就像空中樓閣一般不能存在,所以你的 rownum 條件要包含到 1。

那么,如果想要用 rownum > 5 這種條件的話就要用子查詢,把rownum先生成,然后再對生成結果進行查詢。

示例:

SELECT * FROM ( SELECT e.*, rownum r FROM employee WHERE rownum <= 10 ) t WHERE t.r > 5;

4. 使用rownum的注意事項

  1. 不能對rownum使用>(大於1的數值)、>=(大於1的數值)、=(大於1的數值),否則無結果。
  2. 在使用rownum時,只有當Order By的字段是主鍵時,查詢結果才會先排序再計算rownum,但是,對非主鍵字段(如:name)進行排序時,結果可能就混亂了。出現混亂的原因是:oracle先按物理存儲位置(rowid)順序取出滿足rownum條件的記錄,即物理位置上的前5條數據,然后在對這些數據按照Order By的字段進行排序,而不是我們所期望的先排序、再取特定記錄數。

 

5 下面就是利用包來寫的一個分頁的查詢的過程

 1 -- 包說明
 2 CREATE OR REPLACE PACKAGE pkg_page IS
 3    TYPE page_cur_type IS REF CURSOR;
 4    PROCEDURE get_page_rec(current_page NUMBER, page_size NUMBER, page_rec OUT PAGE_CUR_TYPE);
 5 END pkg_page;
 6 
 7 -- 包體
 8 CREATE OR REPLACE PACKAGE BODY pkg_page IS
 9    -- 分頁查詢的過程
10    PROCEDURE get_page_rec(current_page NUMBER, page_size NUMBER, page_rec OUT PAGE_CUR_TYPE) IS
11          lower_bound NUMBER(4); -- 記錄下限編號
12          upper_bound NUMBER(4); -- 記錄上限編號
13      BEGIN           
14         lower_bound := (current_page - 1) * page_size;
15         upper_bound := current_page * page_size;
16         
17         OPEN page_rec FOR 
18            SELECT id, name, birthday, address, did, salary FROM(  
19              SELECT t1.*,rownum r FROM
20                 (SELECT id, name, birthday, address, did, salary FROM employee ORDER BY name) t1
21              WHERE rownum <= upper_bound
22            ) t
23            WHERE t.r > lower_bound;
24      END get_page_rec;
25 END pkg_page;
26 
27 -- 測試
28 DECLARE
29    page_index NUMBER(4) := 1; -- 頁碼
30    page_size NUMBER(4) := 4; -- 每頁顯示記錄數
31    cur_var PKG_PAGE.page_cur_type;
32    rec employee%ROWTYPE;
33 BEGIN
34    PKG_PAGE.get_page_rec(page_index, page_size, cur_var);
35    LOOP
36      FETCH cur_var INTO rec;
37      EXIT WHEN cur_var%NOTFOUND;
38      DBMS_OUTPUT.PUT_LINE('工號:' || rec.id || ',姓名:' || rec.name || ',工資:' || rec.salary);
39    END LOOP;
40    CLOSE cur_var;
41 END;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM