1. 程式人生 > >oracle分頁查詢資料重複問題、分頁排序陷阱

oracle分頁查詢資料重複問題、分頁排序陷阱

select *
   from (select rownum as rn, ab.*
           from (SELECT t.id,
                        e.ehr_id,
                        nh_code,
                        name,
                        sex,
                        id_card,
                        (to_number(to_char(sysdate, 'yyyy')) -
                        to_number(to_char(birthday, 'yyyy'))) age,home_address,
                        telephone,
                        t.enable_flag,
                        t.create_user,
                        t.create_date,
                        t.modify_date,
                        village_id,
                        (SELECT answer
                           FROM ehr_s_person_answer
                          WHERE ehr_id = e.ehr_id
                            AND question_id = 546) lxrdh,
                        (SELECT count(1)
                           FROM ehr_examination_record
                          WHERE ehr_id = e.ehr_id
                            AND enable_flag = 1) exam_count,
                        (SELECT count(1)
                           FROM ehr_ht_manage_visit_record
                          WHERE ehr_id = e.ehr_id
                            AND enable_flag = 1) visit_count
                   FROM ehr_info e
                   JOIN ehr_hypertension t
                     ON e.ehr_id = t.ehr_id
                    AND t.enable_flag != 3
                  WHERE  e.region_id IN (23)
                    AND e.hosp_id = 1
                  order by sex desc) ab
          where rownum <= 50) abc
  where rn > 40

以上分頁查出來的資料可能會引起分頁資料重複的現象

原因:

1.因為oracle是按塊進行讀取資料的,如果資料按順序儲存,則可能使讀取出來的資料是按順序的,給使用者誤解為預設排序。事實上,oracle沒有進行任何排序操作,如果sql沒有要求排序,oracle會順序的從資料塊中讀取符合條件的資料返回到客戶端。所以在沒有使用排序sql的時候,分頁返回的資料可能是按順序的,也可能是雜亂無章的,這都取決與資料的儲存位置。在oracle分頁查詢過程中,如果資料的物理位置發生了改變,就可能會引起分頁資料重複的現象。 

 2.對於以上SQL指令碼,優化器採用了“SORT (ORDER BY STOPKEY)”。“SORT (ORDER BY STOPKEY)”不需要對所有資料進行排序,而是隻要找出結果集中的按特定順序的最前N條記錄,一旦找出了這N條記錄,就無需再對剩下的資料進行排序,而直接返回結果。這種演算法我們可以視為是“快速排序”演算法的變種。快速排序演算法的基本思想是:先將資料分2組集合,保證第一集合中的每個資料都大於第二個集合中每個資料,然後再按這個原則對每個集合進行遞迴分組,直到集合的單位最小。在進行“SORT (ORDER BY STOPKEY)”時,首先找出N條資料(這些資料並沒有做排序)放在第一組,保證第一組的資料都大於第二組的資料,然後只對第一組資料進行遞迴。可以看到,基於這樣的演算法基礎上,如果N的數值不同,資料的分組也不同(如N=20時,第一次分組比例為12:8,然後繼續遞迴;當N=10時,第一次分組比例為3:7 … …),這樣,在資料的排序欄位值都相等時,輸出結果的順序就會因為N值不同而不同。

解決方法:

   
 select *
   from (select  ab.*,rownum as rn
           from (SELECT id,
                        e.ehr_id,
                        nh_code,
                        name,
                        sex,
                        id_card,
                        to_number(to_char(sysdate, 'yyyy')) -
                        to_number(to_char(e.birthday, 'yyyy')) age,
                        home_address,
                        telephone,
                        t.enable_flag,
                        t.create_user,
                        t.create_date,
                        t.modify_date,
                        village_id,
                        (SELECT answer
                           FROM ehr_s_person_answer
                          WHERE ehr_id = e.ehr_id
                            AND question_id = 546) lxrdh,
                        (SELECT count(1)
                           FROM ehr_examination_record
                          WHERE ehr_id = e.ehr_id
                            AND enable_flag = 1) exam_count,
                        (SELECT count(1)
                           FROM ehr_diabetesMgvisitrecord
                          WHERE ehr_id = e.ehr_id
                            AND enable_flag = 1) visit_count
                   FROM ehr_info e
                   JOIN ehr_diabetes t
                     ON e.ehr_id = t.ehr_id
                  WHERE t.enable_flag != 3
                    AND e.region_id IN (23)
                    AND e.hosp_id = 1
                    order by sex desc,id
                 ) ab) abc
  where rn <= 10
    and rn > 1
後記:

1.後面的方法相對來說對資料庫的效能會有一些影響

2.要正確使用oracle分頁查詢,sql語句中必須有排序條件。

3.排序條件如果沒有唯一性,那麼必須在後邊跟上一個唯一性的條件,比如主鍵

解決方法必須滿足以上2、3方法!!!!!!!!!!!!

參考:http://database.51cto.com/art/201010/231533.htm

   http://blog.csdn.net/bbliutao/article/details/8531091