1、設計原理闡述php
數據查詢分頁,這個功能相信你們都很熟悉,經過數據庫或其它數據源進行查詢操做後,將得到的數據顯示到界面上,可是因爲數據量太大,不能一次性徹底的顯示出來,就有了數據分頁的需求。這個需求在實際開發過程當中仍是廣泛存在的,也給出了不一樣的實現,正常的的幾種思路有:html
一、一次性將全部要查詢的數據查詢出來,而後在客戶端處理,分頁顯示相應的數據。web
二、每次只取我所須要的那部分數據,在服務器端分頁完成後,再發送到客戶端顯示。sql
在asp.net中,GridView控件自帶的分頁功能,就是引用了第一種思路,可是這個方法有很大的弊端,每次請求都是將全部的數據,一次性的讀入到DataTable或DataSet或其它集合當中,而後再分區間顯示出來,顯然形成網絡資源的緊張。而若是在服務器端將數據已經分好頁,再傳送,網絡資源顯然壓力大幅度減小,這樣子就提升了查詢的效率。數據庫
若是在思路2的基礎上,再進行優化,還能夠有如下幾種思路:安全
1)經過SQL語句分頁服務器
2)引用動態SQL語句進行分頁網絡
3)引用存儲過程進行數據分頁oracle
顯然這裏推薦第3種解決方案,理由是:存儲過程因爲在服務器端數據庫已經預先編譯好,不須要運行時編譯,應該能夠直接運行,自己的運行效率比SQL要高;安全性高,防止SQL注入式攻擊(帶參數的SQL語句比簡單的SQL拼接要安全);便於代碼管理和複用,徹底能夠直接將存儲過程代碼保存起來,在下一個項目中直接引用。app
至此,數據查詢分頁原理已經設計完畢,再進一步,能夠引用web頁面靜態化技術(不是僞靜態,就是真的生成html文件),按期的將動態html生成靜態html,這樣能夠有效提升頁面的訪問速度,顯然已經不須要每次再到數據庫中查詢了,省去了數據庫查詢和網絡數據傳送的時間。
2、代碼實例
不管是asp、asp.net、jsp、php仍是其它web開發語言,涉及到分頁這一塊,原理都是想通的,這裏僅以asp.net爲例,完整的設計一個數據查詢分頁功能。
一、徹底本身寫分頁代碼
這個無非就是利用sql語句的分頁功能實現分頁,C#後臺拼接各類字符串,這裏不想過多闡述。
二、引用第三方分頁控件,好比aspnetpager等
首先新建一個分頁實體類:
public class MPage { private string pagesql;//產生的sql語句 private int pagesize;//每頁顯示的條數 private int pageindex;//顯示頁的索引 /// <summary> /// 產生分頁的sql語句 sql要求必須包含rownum字段且其別名爲rn,如例子:select rownum rn,t.* from test t /// </summary> public string Pagesql { get { return pagesql; } set { pagesql = value; } } /// <summary> /// 每頁顯示的條數 /// </summary> public int Pagesize { get { return pagesize; } set { pagesize = value; } } /// <summary> /// 顯示頁的索引 從0開始 /// </summary> public int Pageindex { get { return pageindex; } set { pageindex = value; } } }
分頁查詢類:
/// <summary> /// 獲取分頁的記錄 /// </summary> /// <param name="page">封裝的頁面對象</param> /// <param name="result">反饋的結果</param> /// <returns>結果集的表</returns> public DataTable GetPageRecord(MPage page, out ArrayList result) { OracleParameter[] oracleParameter = new OracleParameter[6]; oracleParameter[0] = new OracleParameter("p_pagesql", OracleType.VarChar); oracleParameter[0].Direction = ParameterDirection.Input; oracleParameter[0].Value = page.Pagesql; oracleParameter[1] = new OracleParameter("p_pagesize", OracleType.Number); oracleParameter[1].Direction = ParameterDirection.Input; oracleParameter[1].Value = page.Pagesize; oracleParameter[2] = new OracleParameter("p_pageindex", OracleType.Number); oracleParameter[2].Direction = ParameterDirection.Input; oracleParameter[2].Value = page.Pageindex; oracleParameter[3] = new OracleParameter("p_totalcount", OracleType.Number); oracleParameter[3].Direction = ParameterDirection.Output; oracleParameter[4] = new OracleParameter("p_pagecount", OracleType.Number); oracleParameter[4].Direction = ParameterDirection.Output; oracleParameter[5] = new OracleParameter("p_currentpagedata", OracleType.Cursor); oracleParameter[5].Direction = ParameterDirection.Output; DataAccess da = new DataAccess(); return da.ExecuteProcedureWithTable(DBConn.sb, ref oracleParameter, "p_app_page", out result); }
用aspnetpager控件和repeater控件結合oracle存儲過程綁定:
/// <summary> /// 用aspnetpager控件和repeater控件結合oracle存儲過程綁定 /// </summary> /// <param name="aspnetpager">aspnetpager控件</param> /// <param name="bindingtarget">repeater控件</param> /// <param name="pagesql">執行的sql語句</param> public void BindingRepeaterWithAspNetPager(AspNetPager aspnetpager, Repeater bindingtarget, string pagesql) { int recordcount = 0; ArrayList result = null; MPage page = new MPage(); page.Pagesize = aspnetpager.PageSize;//每頁顯示的條數 page.Pageindex = aspnetpager.StartRecordIndex / aspnetpager.PageSize;//顯示頁的索引 從0開始 page.Pagesql = pagesql;//產生分頁的sql語句 sql要求必須包含rownum字段且其別名爲rn,如例子:select rownum rn,t.* from test t bindingtarget.DataSource = GetPageRecord(page, out result); bindingtarget.DataBind(); if (result != null && result.Count > 0) { if (int.TryParse(result[3].ToString(), out recordcount)) { aspnetpager.RecordCount = recordcount; } else { aspnetpager.RecordCount = 0; } } }
aspnetpager控件和repeater控件直接綁定datatable:
/// <summary> /// aspnetpager控件和repeater控件直接綁定Datatable /// </summary> /// <param name="aspnetpager">aspnetpager控件</param> /// <param name="bindingtarget">repeater控件</param> /// <param name="dt">Datatable</param> public void BindingRepeaterWithAspNetPagerByDataTable(AspNetPager aspnetpager, Repeater bindingtarget, DataTable dt) { PagedDataSource pds = new PagedDataSource(); pds.AllowPaging = true; pds.PageSize = aspnetpager.PageSize; pds.CurrentPageIndex = aspnetpager.CurrentPageIndex - 1; pds.DataSource = dt.DefaultView; aspnetpager.RecordCount = pds.DataSourceCount; bindingtarget.DataSource = pds; bindingtarget.DataBind(); }
前臺代碼:
<asp:Repeater ID="Repeater1" runat="server"> <HeaderTemplate> <table cellpadding="0" cellspacing="0" border="1" width="100%"> <thead align="center"> <tr> <td style="width: 5%;"> <label> <b>序號</b></label> </td> <td style="width: 10%;"> <label> <b>單位代碼</b></label> </td> <td style="width: 25%;"> <label> <b>單位名稱</b></label> </td> <td style="width: 8%;"> <label> <b>單位申報所屬期</b></label> </td> <td style="width: 8%;"> <label> <b>單位申報基數</b></label> </td> <td style="width: 8%;"> <label> <b>單位申報我的基數</b></label> </td> <td style="width: 8%;"> <label> <b>單位應繳總金額</b></label> </td> <td style="width: 8%;"> <label> <b>單位到賬總金額</b></label> </td> <td style="width: 8%;"> <label> <b>單位到賬時間</b></label> </td> </tr> </thead> </HeaderTemplate> <ItemTemplate> <tr align="center" style='background-color: <%#(Container.ItemIndex%2==0)?"#eeeeee":"#ffffff"%>' onmouseover="this.style.background='#ddeeff'" onmouseout="this.style.background='<%#(Container.ItemIndex%2==0)?"#eeeeee":"#ffffff"%>'"> <td> <label> <%#Eval("rn") %></label><!--序號--> </td> <td> <label> <%#Eval("dwdm") %></label><!--單位代碼--> </td> <td> <label> <%#Eval("dwmc") %></label><!--單位名稱--> </td> <td> <label> <%#Eval("dwsbssq") %></label><!--單位申報所屬期--> </td> <td> <label> <%#Eval("dwsbjs") %></label><!--單位申報基數--> </td> <td> <label> <%#Eval("dwsbgrjs") %></label><!--單位申報我的基數--> </td> <td> <label> <%#Eval("dwyjzje") %></label><!--單位應繳總金額--> </td> <td> <label> <%#Eval("dwdzzje") %></label><!--單位到賬總金額--> </td> <td> <label> <%#Eval("dwdzsj") %><!--單位到賬時間 --></label> </td> </tr> </ItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater> <webdiyer:AspNetPager ID="AspNetPager1" runat="server" AlwaysShow="True" Font-Size="10pt" Font-Names="gb2312" CustomInfoHTML="第%CurrentPageIndex%頁 共%RecordCount%條記錄" ShowCustomInfoSection="Right" SubmitButtonText="跳轉" TextAfterPageIndexBox="頁" OnPageChanged="AspNetPager1_PageChanged" CurrentPageButtonPosition="Center" CustomInfoSectionWidth="45%" CustomInfoTextAlign="Center" PageSize="25" ShowPageIndex="True" Width="92%"> </webdiyer:AspNetPager>
oracle腳本:
create or replace package jssb.pck_page is type T_Page is ref cursor; --定義遊標變量用於返回記錄集 procedure getpagerecord( pindex in number, --分頁索引 psql in varchar2, --產生dataset的sql語句 psize in number, --頁面大小 pcount out number, --返回分頁總數 v_cur out T_Page --返回當前頁數據記錄 ); end pck_page;
create or replace procedure jssb.p_app_GetCount( p_sql in varchar2, p_count out number ) as v_sql varchar2(1000); v_prcount number; begin v_sql := 'select count(*) from (' || p_sql || ')'; execute immediate v_sql into v_prcount; p_count := v_prcount; --返回記錄總數 end p_app_GetCount;
create or replace procedure jssb.p_app_page( p_pagesql in varchar2,--產生分頁的sql語句 sql要求必須包含rownum字段且其別名爲rn,如例子:select rownum rn,t.* from test t p_pagesize in number, --每頁顯示的條數 p_pageindex in number,--顯示頁的索引 從0開始 p_totalcount out number,--總條數 p_pagecount out number,--總頁數 p_currentpagedata out pck_page.T_Page --返回當前頁的數據 ) as begin pck_page.getpagerecord(p_pageindex,p_pagesql,p_pagesize,p_pagecount,p_currentpagedata); p_app_getcount(p_pagesql,p_totalcount); end;
create or replace package body jssb.pck_page is procedure getpagerecord( pindex in number, psql in varchar2, psize in number, pcount out number, v_cur out T_Page ) as v_sql varchar2(1000); v_count number; v_plow number; v_phei number; begin v_sql := 'select count(*) from (' || psql || ')'; execute immediate v_sql into v_count; pcount := ceil(v_count/psize); v_phei := pindex * psize + psize; v_plow := v_phei - psize + 1; --psql := select rownum rn,t.* from test t ; --要求必須包含rownum字段 v_sql := 'select * from (' || psql || ') where rn between ' || v_plow || ' and ' || v_phei ; open v_cur for v_sql; end getpagerecord; end pck_page;