国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

數據庫分頁方法

2024-07-21 02:12:12
字體:
來源:轉載
供稿:網友

最大的網站源碼資源下載站,

方法一:

select top 10 b.* from (select top 20 主鍵字段,排序字段 from 表名 order by 排序字段 desc) a,表名 b where b.主鍵字段 = a.主鍵字段 order by a.排序字段

10 = 每頁記錄數

20 = (當前頁 + 1) * 每頁記錄數

以上語句即可以實現分頁,但是最后取出的結果排序是升序,如果需要結果集為降序(例如時間),則有兩種方法可以處理

1.使用以下語句,但效率可能要降低一些

select * from 表名 b, (select top 10 主鍵字段,排序字段 from (select top 20 主鍵字段,排序字段 from 表名 order by 排序字段 desc) a order by 排序字段 ) c where b.主鍵字段 = c.主鍵字段 order by c.排序字段 desc

2.在ado里處理,將記錄集游標移到最后,然后前移

''以下為asp范例

set rstemp = server.createobject("adodb.recordset")

rstemp.open 語句,conn,1,1

rstemp.movelast

for i = 1 to rstemp.recordcount

 '取值....

rstemp.moveprevious

next

 

經測試,以上分頁方法比使用臨時表分頁速度還要快,并且簡單易用.

方法二:

大數據量下的分頁

    對于非常大的數據模型而言,分頁檢索時,每次都加載整個數據源非常浪費。通常的選擇是檢索頁面大小的塊區的數據,而非檢索所有的數據,然后單步執行當前行。

    本文演示asp.net的datagrid和sql server 實現大數據量下的分頁,為了便于實現演示,數據表采用了northwind數據庫的orders表(830條記錄)。

    如果數據表中有唯一的自增索引,并且這個字段沒有出現斷號現象。檢索頁面大小的塊區數據就非常簡單了。通過簡單的sql語句就可以實現這個功能:

    select * from orders where orderid between 10248 and 10253

    其中,開始編號為:(currentpageindex - 1) * pagesize  結束編號為:currentpageindex * pagesize

    當然,如果這個字段斷號不是很嚴重,而且允許不是很嚴格的按照每頁條數分頁,這樣的方法也是可以用的。

    如果這個字段斷號,或者需要按照其他條件排序分頁,就要復雜些了。首先要獲得這個頁面需要顯示的編號,然后再按照這個編號獲得需要的塊區數據。根據編號獲得塊區數據很簡單。不過用下面方式獲得數據排序并不是按照指定的id列表順序,這時候還要附加order by 命令。

select * from orders where orderid in (10248,10249,10250,10251,10252,10253) order by orderid desc

    獲得這個頁面需要顯示的編號列表就復雜多了,而且有多種方案:

方案一:維護一個表,這個表記錄需要顯示的這些編號排序順序。(這個表可以是臨時表,也可以是物理表)。下面演示了利用一個全局臨時表。這個全局臨時表記錄需要顯示的編號。注意排序,這里的order by 就是需要顯示的排序順序。

create table ##temptable(iid int identity (1, 1) not null,mainid int not null)insert ##temptable(mainid) select orderid from orders order by orderid descselect * from ##temptabledrop table ##temptable -- 實際執行時候,刪除全部臨時表當然不再這里執行。

這個臨時表存在,獲得指定分頁的分塊數據就很簡單了。看下面代碼:

create table ##temptable(iid int identity (1, 1) not null,mainid int not null)insert ##temptable(mainid) select orderid from orders order by orderid descdeclare @pagesize int,@currpage int,@strsql varchar(2000),@idstr varchar(1000)select @pagesize = 30select @currpage = 2select @idstr = ''select @idstr = @idstr + ltrim(rtrim(str(mainid))) + ',' from ##temptable where iid between ((@currpage-1)*@pagesize+1) and @currpage*@pagesizeif @idstr <> '' begin select @idstr = left(@idstr,len(@idstr)-1)endselect @strsql = 'select * from orders where orderid in ('[email protected]+')  order by orderid desc 'exec(@strsql)drop table ##temptable

注意:實際使用這個方案的時候,還要考慮何時更新這個全局臨時表,一般是放到計劃任務中,定時更新這個匯總表。

方案二:每次都去查詢,每次獲得最新的編號順序。由于這時候不存在這個臨時表,書寫獲得需要顯示頁面的編號的字符串就需要點技巧,看下面的代碼:asp.net 的 datagrid 提供了使用這種分區的數據的方法。 datagrid 通過 allowcustompaging 和 virtualitemcount 屬性支持塊區操作。如果 allowcustompaging 為 true,則 datagrid 不會根據 currentpageindex 計算數據模型中的起始顯示位置。datagrid 將顯示數據模型中的所有數據,而頁導航欄將當前位置報告為 (virtualitemcount+pagesize-1)/pagesize 之 currentpageindex 頁。下面的示例說明此功能。

declare @pagesize int,@currpage int,@topnum int,@previous intselect @pagesize = 30select @currpage = 2select @topnum = @currpage * @pagesizeselect @previous = (@currpage - 1) * @pagesizedeclare @i int,@idstr nvarchar(500),@strsql nvarchar(1000)select @i = 0select @strsql = n''select @strsql = @strsql + n' select top '+str(@topnum)+ ' @i = @i + 1 'select @strsql = @strsql + n',  @idstr = 'select @strsql = @strsql + n'case when @i > '+str(@previous)+' then  @idstr + ltrim(rtrim(str(orderid))) + '','' 'select @strsql = @strsql + n'else n''''end 'select @strsql = @strsql + n'from orders 'select @strsql = ltrim(rtrim(@strsql)) + n' order by orderid desc 'select @idstr = n''exec sp_executesql @strsql,n'@i int,@idstr varchar(500) output',@i,@idstr outputif len(rtrim(ltrim(@idstr))) > 0begin select @idstr = left(@idstr,len(@idstr)-1)endselect @strsql = 'select * from orders where orderid in ('[email protected]+')'exec(@strsql)

 

     protected void binddatagrid(int currpage) {  string strconn = "data source=(local);integrated security=sspi;database=northwind";  // 請確認 機器名/aspnet 用戶可以訪問northwind數據庫  sqlcommand cmd = new sqlcommand();  sqlconnection conn = new sqlconnection(strconn);  sqlparameter[]  parms = new sqlparameter[] {   new sqlparameter("@pagesize",sqldbtype.int),   new sqlparameter("@currpage",sqldbtype.int),   new sqlparameter("@searchsql",sqldbtype.nvarchar,128),   new sqlparameter("@count",sqldbtype.int),  };  parms[0].value = datagrid1.pagesize;  parms[1].value = (currpage+1);   //  數據庫的分頁算法第一頁是1  datagrid的第一頁是0  parms[2].value = dbnull.value;  parms[3].direction = parameterdirection.output;  parms[3].value = dbnull.value;  dataset ds = new dataset();  try   {   if (conn.state != connectionstate.open) conn.open();   cmd.connection = conn;   cmd.commandtext = "selected_page_list";   cmd.commandtype = commandtype.storedprocedure;   if (parms != null)    {    foreach (sqlparameter parm in parms)     cmd.parameters.add(parm);   }   sqldataadapter da = new sqldataadapter(cmd);   da.fill(ds);   int aa = convert.toint32(parms[3].value.tostring());   cmd.parameters.clear();   if (currpage == 0)   {    datagrid1.virtualitemcount = aa;   }   datagrid1.currentpageindex = currpage;   datagrid1.datasource = ds;   datagrid1.databind();  }  catch(exception ewx)  {   conn.close();   response.write (ewx.message.tostring());   response.end();  } }    void page_load(object sender, eventargs e ) {  if (!ispostback)   {   binddatagrid(0);   // 第一次打開這個頁面,訪問分頁的第一頁  }    }    void mydatagrid_page(object sender, datagridpagechangedeventargs e) {  binddatagrid(e.newpageindex);    }

如果你有更多數據量的表稍加修改,也可以使用本演示程序。其下是演示代碼下載,演示代碼使用的是方案二。使用方法看readme.txt文件。

整個演示代碼 下載

http://chs.gotdotnet.com/quickstart/aspplus/samples/webforms/ctrlref/webctrl/datagrid/doc_datagrid.aspx#paging
這里演示了利用datagrid 的這個功能(沒有本文中討論的利用存儲過程獲得分區數據)。如對datagrid的這個功能不太熟悉,請先看這里。

 

方法三:

雖然 datagrid 控件自己帶了一個分頁處理機制,但它是將符合查詢條件的所有記錄讀入內存,然后進行分頁顯示的。隨著符合條件的記錄數目增多,就會出現運行效率問題,或者至少是資源的利用率下降。

下面的代碼示例都以下面的表結構為準:

 

 articles 表sql server 類型oracle 類型
pkidint (自增)number(9) (插入時在當前最大值上加1)
 authornvarchar(10)nvarchar2(10)
 titlenvarchar(50)nvarchar2(50)
 pubtimedatetimedate

sql server / access 等微軟產品中,我們通常的自定義分頁有兩種思路:

一種是以 asp.net forum 為代表的、“臨時表”方法:即在存儲過程中建立一個臨時表,該臨時表包含一個序號字段(1,2,3,....)以及表的主鍵(其他能夠唯一確定一行記錄的字段也是可以的)字段。存儲過程可能如下:(編號 ss1)

create procedure getallarticles_paged
(
     @pageindex int,
     @pagesize int,
     @totalrecords out int,
     @totalpages out int
)
as

declare @pagelowerbound int
declare @pageupperbound int

-- set the page bounds
set @pagelowerbound = @pagesize * @pageindex
set @pageupperbound = @pagelowerbound + @pagesize + 1

-- create a temp table to store the select results
create table #tmp
(
     recno int identity (1, 1) not null,
     articleid int
)

insert into #tmp
     select [id]
     from articles
     order by pubtime desc

select a.*
from articles a (nolock), #tmp t
where a.id = t.articleid and
     t.recno > @pagelowerbound and
     t.recno < @pageupperbound
order by t.recno

go

另一種可能更適合程序中“拼湊” sql 語句:用兩次 top 命令取得我們所要的分頁數據,例如:(編號 ss2)

select * from
     (
     select top(pagesize) * from
     (
          select top (pagesize * pageindex) *
          from articles
          order by pubtime desc
     )
     order by pubtime asc
)
order by pubtime desc

這個的想法就是“掐頭去尾”,還有不少分頁的方法,這里就不一一列出了。

對于 oracle 數據庫,有幾處不同嚴重妨礙了上面幾個方法的實施,比如,oracle 不支持 top 關鍵字:不過這個好像并不十分嚴重,因為它提供了 rownum 這個隱式游標,可以實現與 top 類似的功能,如:

select top 10 ... from where ...

要寫成

select ... from ... where ... and rownum <= 10

rownum 是記錄序號(1,2,3...),但有一個比較麻煩的事情是:如果 sql 語句中有 order by ... 排序的時候,rownum 居然是先“標號”后排序!這樣,這個序號如果不加處理是不合乎使用需求的。

至于臨時表,oracle 的臨時表和 sql server 的有很大不同,我還沒搞懂這個東西,就不妄加揣測了。

國內網站中介紹 oracle 分頁的資料很少,我找到了一個國外站點(www.faqts.com)的一篇 faq,根據這篇文章的介紹,可以如下分頁:(編號 ora1)

select * from
     (
     select a.*, rownum r
     from
          (
          select *
          from articles
          order by pubtime desc

          ) a
     where rownum <= pageupperbound
     ) b
where r > pagelowerbound;

其中藍色部分可以改為任意的、需要的 sql select 語句,這點倒是挺方便的。

方法四:

今天突然發現,oracle原來可以這樣實現分頁功能:

select * from (select rownum rdd,field1,field2 from t_table where rownum<=400) where  rdd>200

上述語句實現了從第201條記錄開始處取200條記錄

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 鱼台县| 沅陵县| 新宁县| 宣汉县| 镇江市| 南投市| 平邑县| 确山县| 海晏县| 临江市| 宁陕县| 巨鹿县| 大足县| 浪卡子县| 青浦区| 孙吴县| 鄂伦春自治旗| 曲周县| 黄骅市| 三亚市| 江西省| 清丰县| 台安县| 雅安市| 疏附县| 十堰市| 德江县| 东丽区| 缙云县| 肇源县| 涟源市| 东源县| 罗甸县| 湘乡市| 乐陵市| 东乡族自治县| 梧州市| 三亚市| 呼图壁县| 阳曲县| 光泽县|