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

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

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

    隨筆 - 312, 文章 - 14, 評(píng)論 - 1393, 引用 - 0
    數(shù)據(jù)加載中……

    用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能

    本文為原創(chuàng),如需轉(zhuǎn)載,請(qǐng)注明作者和出處,謝謝!

        Web系統(tǒng)雖然現(xiàn)在很流行,但是分頁(yè)問(wèn)題一直長(zhǎng)期困擾著Web系統(tǒng)的開(kāi)發(fā)人員。對(duì)于不同的數(shù)據(jù)庫(kù),可能開(kāi)發(fā)人員對(duì)分頁(yè)的處理分有很大差別。個(gè)人認(rèn)為,使用MySQL開(kāi)發(fā)Web系統(tǒng)的程序員是感到最舒服的,因?yàn)椋?/span>MySQL中提供了limit語(yǔ)句,可以獲得查詢結(jié)果的一段數(shù)據(jù)。如下面的SQL語(yǔ)句所示:

    select * from table1 limit 120

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

        對(duì)于其他的數(shù)據(jù)庫(kù),恐怕就沒(méi)MySQL那么容易查詢出記錄段了。在SQL Server2005中也提供了類似MySQL的處理方法(可以使用ROW_NUMBER()函數(shù)來(lái)實(shí)現(xiàn)這個(gè)功能),SQL語(yǔ)句如下:

     

    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語(yǔ)句雖然也可以實(shí)現(xiàn)和MySQL一樣的功能,但卻比MySQLlimit復(fù)雜一些。

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

        在本文給出一種直接使用Web中的Session對(duì)象來(lái)方式來(lái)實(shí)現(xiàn)分頁(yè)的功能,Session是在Web系統(tǒng)中保存當(dāng)前分話數(shù)據(jù)的。我們可以想象。分頁(yè)的難點(diǎn)在哪里,就象MySQL中的limit語(yǔ)句一樣,只需要有兩個(gè)值:起使記錄數(shù)和要獲得的記錄總數(shù)就可以了。要獲得的記錄總數(shù)這個(gè)我們很容易知道,一般就是分一頁(yè)的記錄數(shù)。但是起使記錄數(shù)卻很難獲得。

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

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

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

        先拿Java為例來(lái)說(shuō)明一下。下面的代碼在Session中記錄了第一頁(yè)到最后一頁(yè)的起始id:

     

    //  rs為記錄集,其他語(yǔ)言的操作類似
    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來(lái)定位記錄,并取出當(dāng)前記錄的id值(一個(gè)自增字段),并將其保存在Session中。

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

        1 51 123 179 229 290 367 567 699

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

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

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

        上面的方法還有一些問(wèn)題,如當(dāng)?shù)谝淮畏祷氐挠涗浐芏嗟脑?,使?/span>absolute方法進(jìn)行循環(huán)所有的記錄可能有些慢,那可以在程序中做個(gè)約定,只循環(huán)41次,也就是保存前40頁(yè)的記錄,當(dāng)用戶要查看第41頁(yè)的話,再取出第40頁(yè)的開(kāi)始記錄的id值,將再次查詢從該id值往后的所有記錄,再記錄40頁(yè)的id值,也就是這時(shí)已經(jīng)有80頁(yè)的id記錄被保存在Session中的。以此類推,

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

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

        如果使用的是其他數(shù)據(jù)庫(kù),沒(méi)有類型top的關(guān)鍵字,可以在查詢時(shí)多加一個(gè)區(qū)間,如用戶要查詢第2頁(yè)的數(shù)據(jù),可以將第2頁(yè)和第3頁(yè)的都查出來(lái),這樣一般就可以獲得超過(guò)50條的記錄。但如果記錄數(shù)還不夠(這個(gè)表的記錄被刪除的太多了),筆者建議重新查詢所有的記錄,重新更新一下Session對(duì)象中的id值。

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

        本分頁(yè)方法適合于所有的數(shù)據(jù)庫(kù),無(wú)論是網(wǎng)絡(luò)數(shù)據(jù)庫(kù)(Oracle、SQL Servlet、DB2等),以及桌面數(shù)據(jù)庫(kù)(accessparadoxpdf等)。并且不需要在數(shù)據(jù)庫(kù)中建立額外的資源,如存儲(chǔ)過(guò)程等。(當(dāng)然,每個(gè)表需要有一個(gè)自增類型字段,這一點(diǎn)很關(guān)鍵)。

        補(bǔ)充一下,這種方法只適合于一個(gè)排序字段的查詢,而且這個(gè)排序字段值不能有重復(fù)的,也就是說(shuō)得是有唯一索引的字段。在本文中使用了自增鍵來(lái)說(shuō)明,但也可以 是其他字段,如不重復(fù)的時(shí)間字段,按時(shí)間排序后??梢允褂帽疚牡姆椒?。而且唯一字段區(qū)間值也可以使用其他的方式保存,如viewstate,hide input等。 

        哪位讀者有更好,更通用的分頁(yè)方法(最好不要在數(shù)據(jù)庫(kù)中建立象存儲(chǔ)過(guò)程一樣的資源,盡量不要使用與數(shù)據(jù)庫(kù)相關(guān)的語(yǔ)句,如SQL Server中的top),請(qǐng)跟貼。

     

     





    Android開(kāi)發(fā)完全講義(第2版)(本書(shū)版權(quán)已輸出到臺(tái)灣)

    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 銀河使者 閱讀(2576) 評(píng)論(7)  編輯  收藏 所屬分類: SQL Serverdatabasesmysql 、oracle 、web 、 原創(chuàng)

    評(píng)論

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

    學(xué)習(xí)了
    2008-08-24 11:12 | R_XiaoGuang

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

    分頁(yè)不應(yīng)該是困擾開(kāi)發(fā)人員的一個(gè)技術(shù)難點(diǎn)
    2008-08-25 10:46 | lzycxy

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

    關(guān)鍵是性能問(wèn)題,實(shí)現(xiàn)很容易。
    2008-08-25 11:52 | 銀河使者

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

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

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

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

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

    學(xué)習(xí)了 感謝
    2008-08-27 14:23 | viper007

    # re: 用Session和唯一索引字段實(shí)現(xiàn)通用Web分頁(yè)功能  回復(fù)  更多評(píng)論   

    又學(xué)到新東西了,謝謝
    2008-09-07 00:47 | 幻想
    主站蜘蛛池模板: 亚欧国产一级在线免费| 拍拍拍又黄又爽无挡视频免费| 免费人成在线观看视频高潮| 亚洲福利秒拍一区二区| 又大又硬又爽免费视频| 成年免费大片黄在线观看岛国| 日韩a级无码免费视频| 三级片免费观看久久| 亚洲人成小说网站色| 久久亚洲国产成人精品性色| 国产AV无码专区亚洲AV漫画| 国产裸模视频免费区无码| 日本阿v免费费视频完整版| 久久中文字幕免费视频| 精品一区二区三区高清免费观看 | 亚洲无mate20pro麻豆| 无码乱人伦一区二区亚洲一| 亚洲人成网7777777国产| 亚洲第一网站男人都懂| 免费观看理论片毛片| 国产三级在线观看免费| 欧洲乱码伦视频免费| 亚洲人成免费网站| **俄罗斯毛片免费| 日韩精品极品视频在线观看免费| 丁香花在线视频观看免费| 中文字幕a∨在线乱码免费看 | 无码日韩精品一区二区免费| 亚洲一区二区三区免费观看| 精品无码无人网站免费视频| 久久久久久影院久久久久免费精品国产小说 | 亚洲成a∧人片在线观看无码| 亚洲人成网国产最新在线| 亚洲精品国产日韩| 亚洲精品无码永久在线观看男男 | 免费能直接在线观看黄的视频| 最好看的中文字幕2019免费| 91福利视频免费观看| 国产精品1024永久免费视频| 麻豆国产精品免费视频| 中文字幕无码免费久久99|