隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2008年8月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          公告

          關注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網站

          關注的網站

          協議

          喜歡的Blog

          國內廣告平臺

          圖書出版

          在線培訓

          開發工具

          微博客戶端

          手機鈴聲

          操作系統

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統

          數學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1972285
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          用Session和唯一索引字段實現通用Web分頁功能

          本文為原創,如需轉載,請注明作者和出處,謝謝!

              Web系統雖然現在很流行,但是分頁問題一直長期困擾著Web系統的開發人員。對于不同的數據庫,可能開發人員對分頁的處理分有很大差別。個人認為,使用MySQL開發Web系統的程序員是感到最舒服的,因為,在MySQL中提供了limit語句,可以獲得查詢結果的一段數據。如下面的SQL語句所示:

          select * from table1 limit 120

              上面的SQL表示從table1中查出記錄,并返回從第2條開始的20條記錄(第1條記錄從0開始)。

              對于其他的數據庫,恐怕就沒MySQL那么容易查詢出記錄段了。在SQL Server2005中也提供了類似MySQL的處理方法(可以使用ROW_NUMBER()函數來實現這個功能),SQL語句如下:

           

          With t AS 
          (
              
          SELECT contactid, namestyle, lastname,
              ROW_NUMBER() 
          over(order by namestyle) as RowNumber 
              
          FROM Person.Contact
          )
          select * from t
          Where RowNumber Between 20 and 30

              雖然上面的SQL語句雖然也可以實現和MySQL一樣的功能,但卻比MySQLlimit復雜一些。

              如果在數據庫中提供了實現Web分頁的機制,就算復雜一些,也是可以解決的。但有效數據庫可能并未提供這種機制。這就得使用更復雜的方法來實現Web分頁,如在SQL Server2000中未提供ROW_NUMBER()函數,就有很多開發人員通過編寫分頁的存儲過程來處理。這樣做既復雜,又不通用。假設要移植到Oracle上,還得費一番功夫。

              在本文給出一種直接使用Web中的Session對象來方式來實現分頁的功能,Session是在Web系統中保存當前分話數據的。我們可以想象。分頁的難點在哪里,就象MySQL中的limit語句一樣,只需要有兩個值:起使記錄數和要獲得的記錄總數就可以了。要獲得的記錄總數這個我們很容易知道,一般就是分一頁的記錄數。但是起使記錄數卻很難獲得。

              如果使用自增鍵當然可以,但這要建立在表只增不刪,而且id1或一個已知的起始位置開始的情況。如果刪除了表中的一些數據,自增鍵就不再是從1n,依次遞增了。也就是中間可能有空檔。如自增鍵從20100,中間可能只有10條記錄。因此,單純使用自增鍵并不能很好地解決分頁問題。

              但卻可以將Session和自增鍵組合來解決分頁問題。大家可以設想,在用戶第一次查詢時,如select * from table1 where field1 like '%abc%',這時將記錄全部查出。假設每頁顯示50條記錄,這時可以從頭開始取出50條記錄。這不會有任何問題。然后,當用戶要查看第2頁時,最普通的做是再執行一次上面的SQL語句,然后從第51第記錄開始,再取出50條記錄。如果這樣做,將大大浪費服務器的資源。

              為了解決這個問題,可以在每一次執行完上面的SQL語句后,除了取出前50條記錄外,再通過記錄的定位,將其他頁面的起始id值保存在Session中(可以放在List對象中)。然后在用戶要查看第2頁或后面的頁時,直接從Session中取出該頁起始id的值,如果使用的是SQL Servlet數據庫,可以使用top n,其中n表示每頁記錄數,來查詢當前頁的記錄。

              先拿Java為例來說明一下。下面的代碼在Session中記錄了第一頁到最后一頁的起始id:

           

          //  rs為記錄集,其他語言的操作類似
          ResultSet rs = stmt.executeQuery("select * from table1 where field1 like '%abc%'");  
          int n = 1;
          while(rs.absolute(n))
          {
              
          int id = rs.getInt(id)
              
          //  將id保存在Session中
              n += 50;
          }

              從上面的代碼可以看出,使用ResultSetabsolute來定位記錄,并取出當前記錄的id值(一個自增字段),并將其保存在Session中。

              假設共查詢出500條記錄,那么Session中保存的id值有可能是下面的樣子:

              1 51 123 179 229 290 367 567 699

              從上面的id值可以看出,中間有斷檔。但這9id值之間的記錄數都是50個。如下面的SQL語句將查詢出50個記錄:   

          select * from table1 where field1 like '%abc%' and (id >= 290 and id < 367)

              假設用戶要查看第3頁的話,就會取出123179,并將其加入select 語句的where條件,類似上面的SQL語句。這樣用戶除了第一次查詢外,查看其他頁都會只返回當前頁面的記錄了。

              上面的方法還有一些問題,如當第一次返回的記錄很多的話,使用absolute方法進行循環所有的記錄可能有些慢,那可以在程序中做個約定,只循環41次,也就是保存前40頁的記錄,當用戶要查看第41頁的話,再取出第40頁的開始記錄的id值,將再次查詢從該id值往后的所有記錄,再記錄40頁的id值,也就是這時已經有80頁的id記錄被保存在Session中的。以此類推,

              當然,這種方法也不可避免地遇到刪除記錄的情況,如果用戶正在查看頁面,這時某一頁的記錄被刪除了,當用戶再次要查看這頁時,根據Session中保存的id區間,就會得到少于50的記錄。在這種情況下,如果使用的是SQL Servlet,就好辦一些,可以在where條件中只加id的上限,不加下限,然后使用top關鍵字來限制查詢出的記錄數,SQL語句如下:

          select top 50 * from table1 where field1 like '%abc%' and id >= 290

              如果使用的是其他數據庫,沒有類型top的關鍵字,可以在查詢時多加一個區間,如用戶要查詢第2頁的數據,可以將第2頁和第3頁的都查出來,這樣一般就可以獲得超過50條的記錄。但如果記錄數還不夠(這個表的記錄被刪除的太多了),筆者建議重新查詢所有的記錄,重新更新一下Session對象中的id值。

              總之,本算法就是在第一次查詢時預先將后面頁面的起始記錄的id值事先保存起來,然后等待以后查看其他頁面時使用。如果這時某個頁面的記錄被刪除(如果當前頁面記錄數不足頁面記錄總數,被示為有記錄刪除),可以重新更新一下Session中的id值,然后根據新的id值再查一遍。但要注意的是這個id值最好使用數據庫的自增型字段(一般的數據庫,甚至桌面數據庫都會有自增型字段類型)。為了盡量避免總更新Session中的id值,可以在查詢一個頁面時查詢出兩個頁面的記錄,這樣在一般情況下,會保證記錄數超過頁面記錄總數。但這樣做一個缺點,就是可能兩個相鄰頁面的記錄有一定的重復。不過并沒有太大影響。我們在網上看某些論壇的貼子時,有時可能也會發現兩個相鄰頁面的記錄有重復。

              本分頁方法適合于所有的數據庫,無論是網絡數據庫(OracleSQL Servlet、DB2等),以及桌面數據庫(access、paradox、pdf等)。并且不需要在數據庫中建立額外的資源,如存儲過程等。(當然,每個表需要有一個自增類型字段,這一點很關鍵)。

              補充一下,這種方法只適合于一個排序字段的查詢,而且這個排序字段值不能有重復的,也就是說得是有唯一索引的字段。在本文中使用了自增鍵來說明,但也可以 是其他字段,如不重復的時間字段,按時間排序后。可以使用本文的方法。而且唯一字段區間值也可以使用其他的方式保存,如viewstate,hide input等。 

              哪位讀者有更好,更通用的分頁方法(最好不要在數據庫中建立象存儲過程一樣的資源,盡量不要使用與數據庫相關的語句,如SQL Server中的top),請跟貼。

           

           





          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2008-08-23 17:55 銀河使者 閱讀(2574) 評論(7)  編輯  收藏 所屬分類: SQL Serverdatabasesmysql 、oracle 、web 原創

          評論

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          學習了
          2008-08-24 11:12 | R_XiaoGuang

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          分頁不應該是困擾開發人員的一個技術難點
          2008-08-25 10:46 | lzycxy

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          關鍵是性能問題,實現很容易。
          2008-08-25 11:52 | 銀河使者

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          session里面不應該放那么多東西吧,很影響性能的.
          2008-08-26 08:59 | miaomiao

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          session就是個Map,一般不會影響性能。
          2008-08-26 09:05 | 銀河使者

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          學習了 感謝
          2008-08-27 14:23 | viper007

          # re: 用Session和唯一索引字段實現通用Web分頁功能  回復  更多評論   

          又學到新東西了,謝謝
          2008-09-07 00:47 | 幻想
          主站蜘蛛池模板: 枣阳市| 龙岩市| 阳谷县| 奎屯市| 揭东县| 襄汾县| 荥经县| 彰武县| 湘乡市| 基隆市| 邳州市| 浠水县| 桃江县| 三门峡市| 荃湾区| 舟曲县| 巧家县| 得荣县| 蒙自县| 定安县| 余干县| 茶陵县| 来安县| 正定县| 盐亭县| 龙岩市| 晋州市| 大邑县| 广丰县| 台东市| 台山市| 历史| 商河县| 崇信县| 含山县| 钦州市| 乌恰县| 中阳县| 宜丰县| 腾冲县| 大埔区|