<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

    用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 ServletDB2等),以及桌面數據庫(accessparadoxpdf等)。并且不需要在數據庫中建立額外的資源,如存儲過程等。(當然,每個表需要有一個自增類型字段,這一點很關鍵)。

        補充一下,這種方法只適合于一個排序字段的查詢,而且這個排序字段值不能有重復的,也就是說得是有唯一索引的字段。在本文中使用了自增鍵來說明,但也可以 是其他字段,如不重復的時間字段,按時間排序后。可以使用本文的方法。而且唯一字段區間值也可以使用其他的方式保存,如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 銀河使者 閱讀(2573) 評論(7)  編輯  收藏 所屬分類: SQL Serverdatabasesmysqloracleweb 原創

    評論

    # 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 | 幻想
    主站蜘蛛池模板: 久久久久亚洲AV片无码| 亚洲午夜成人精品电影在线观看| 在线视频免费观看www动漫| 日本19禁啪啪无遮挡免费动图| 亚洲国产精品激情在线观看| 亚洲精品国产精品乱码不卡√| 久久久久亚洲AV无码永不| 亚洲欧洲无码一区二区三区| 一级毛片免费播放视频| 日韩精品无码一区二区三区免费| 思思99re66在线精品免费观看| 亚洲AV中文无码乱人伦在线视色| 亚洲AV无码一区二区三区系列 | 国产成人免费片在线观看| 国产亚洲av片在线观看18女人 | 亚洲精品无码久久久影院相关影片 | 国产h视频在线观看免费| 国产男女猛烈无遮档免费视频网站 | 免费观看黄网站在线播放| 亚洲国产精品人人做人人爱| 中文字幕在线观看亚洲| 亚洲av日韩精品久久久久久a| 成全在线观看免费观看大全 | 亚洲AV成人影视在线观看| 久久国产一片免费观看| 国产99视频精品免费观看7| 亚洲毛片av日韩av无码| 亚洲国产成人九九综合| 一级人做人a爰免费视频| 在线看片韩国免费人成视频| 国产精品亚洲不卡一区二区三区 | 亚洲日本香蕉视频观看视频| 免费人成视频在线观看免费| 18观看免费永久视频| 亚洲AV无码成H人在线观看| 亚洲国产日产无码精品| 国产无遮挡色视频免费观看性色| 一个人在线观看视频免费| 亚洲国产成人片在线观看无码 | 国产精品免费一级在线观看| 亚洲精品偷拍无码不卡av|