日期:2011-09-14  浏览次数:20856 次

一:一个老生常谈的问题。
    我们知道,记录集分页是数据库处理中十分常见的问题。而当我们设计到网络数据库,就是说要考虑传输带宽问题时,分页问题就每每困扰着每一个数据库程序设计人员。

二:分页问题的解决方案汇总
    说起解决的方案,每个数据库设计人员可能都会举出许多方法。但细分后,可以归为三类。一:Ado纪录集分页、二:专储记录集分页、三、数据库游标分页。
 一:著名的ADO纪录集分页。
     说到著名,因为这个可能是最简单和常见的分页方法了。(可能也是用的最多的)就是利用ADO自带的分页功能来实现分页。
     具体流程为,数据库根据查询语句返回一个完整的纪录集。然后到客户端后有客户端的游标进行分页。他们大多数由ADO自带的Recordset对象就可以实现了。可能涉及到的属性有:
recordset.pagesize:每页输出纪录集的大小
recordset.AbsolutePage: 当前输出的页    (有以上的两个属性其实就可以完成分页输出了)
recordset.pagecount: 目前的总页数。
     这种方法好不好呢,有的人说是十分好,也有人说效率不高。其实这的根据实际的应用状况来确定,如果是单机数据库,或者是局域网环境,或者数据库纪录较少,则他都是很好的分页方法,而且如果不涉及到网络和更新较少的环境里,则他可以说是最好的分页方法。因为它可以先生成一个缓存记录集,以后的几页纪录都可以不通过数据库来取即可。但是,如果涉及到网络,或者是更新频繁。他就不是很实用的了。

列举程序。(我们都用网络问题来考虑)
 
nowpage=Request("nowpage") '当前的输出页
if nowpage="" or nowpage<1 then nowpage=1

set rs=server.CreateObject("adodb.recordset")
rs.CursorType=1
sql="select * from table1 "
rs.open sql,strconn (strconn为连接字段,已定义过)

rs.PageSize=20  '当前页的大小
if cint(nowpage)>rs.pagecount then nowpage=rs.pagecount
rs.AbsolutePage=nowpage

'然后输出当前一页的纪录
'.............


还可以提供一下程序属性设置。
首页:nowpage=1
前页:nowpage=nowpage-1
下页:nowpage=nowpage+1
尾页:nowpage=rs.pagecount
总纪录数:rs.recordcount
总页数:rs.pagecount

二:转储纪录集分页。
这种方法诞生于网络时代,就是利用服务器端的强大处理过程,先将目标数据库存到一个临时的数据库里,并且加上一个自增字段来进行划分页面,最后将所需固定数目的纪录集传回。

优点是:只需交互一次,而且返回固定一页的纪录集。
缺点是:如果纪录集增大时则每次都需建立一个临时纪录集,也比较耗时间,但减少了网络传输量。
例子:


取自 Worx 英文版的<<Professional Active Server Pages 3.0>>
ISBN1861002610
关键地方我已作了中文翻译

CREATE PROCEDURE usp_PagedAuthors
@iPage int,
@iPageSize int
AS
BEGIN
-- disable row counts
SET NOCOUNT ON

-- declare variables
DECLARE @iStart int -- start record
DECLARE @iEnd int -- end record
DECLARE @iPageCount int -- total number of pages

-- create the temporary table
       --建立临时表。

CREATE TABLE #PagedAuthors        (
--这个自增字段十分关键,就是靠他来完成分页标示。
ID int IDENTITY,      
au_id varchar(11) NOT NULL ,
au_lname varchar(40) NOT NULL ,
au_fname varchar(20) NOT NULL ,
phone char(12) NOT NULL ,
address varchar(40) NULL ,
city varchar(20) NULL ,
state char(2) NULL ,
zip char(5) NULL ,
contract bit NOT NULL 
)

-- populate the temporary table       
--先转存到上面的这个纪录集。
INSERT INTO #PagedAuthors (au_id, au_lname, au_fname, 
phone, address, city, state, zip, contract)
SELECT au_id, au_lname, au_fname, 
phone, address, city, state, zip, contract
FROM authors


-- work out how many pages there are in total
SELECT @iPageCount = COUNT(*)
FROM  authors

SELECT @iPageCount = CEILING(@iPageCount / @iPageSize) + 1

-- check the page number
IF @iPage < 1
SELECT @iPage = 1

IF @iPage > @iPageCount
SELECT @iPage = @iPageCount

-- calculate the start and end records
SELECT @iStart = (@iPage - 1) * @iPageSize
SELECT @iEnd = @iStart + @iPageSize + 1

-- select only those records that fall within our page
--这条sql语句就是选取固定的纪录集。

SELECT au_id, au_lname, au_fname, 
phone, address, city, state, zip, contract
FROM #PagedAuthors
WHERE ID > @iStart
AND ID < @iEnd


DROP TABLE #PagedAuthors

-- turn back on record counts
SET NOCOUNT OFF

-- Return the number of records left
RETURN @iPageCount
END


而输出端可以用最快类型的ADO"火线光标"顺次输出就可
<%
  Dim cmdAuthors
  Dim rsData
  Dim iPage
  Dim iLastPage
  Dim sQuote

  sQuote = Chr(34)

 ' get the requested data
  If Request.QueryString("PAGE") = "" Then
    iPage = 1
  Else
    iPage = CInt(Request.QueryString("PAGE"))

    If iPage < 1 Then
      i