简介
在 Active Server Pages (ASP) 应用程序中显示大型记录集,很可能是您熟悉的一个问题。本文对此问题及其解决方案和示例代码进行了深入探讨,这个示例代码经过简单修改,就可以应用于您的具体情况。该示例代码被设计成服务器端的解决方案,它与浏览器无关。另外,我会指出您在设计自己的解决方案时需要考虑的问题。
问题
您的查询返回了一个大型记录集。需要提供一个简便方法来浏览这些结果,即在每页上只显示结果的子集。要有效的完成此项工作,需要对 ActiveX(R) 数据对象 (ADO) 和数据库如何协同工作有深入的了解。
解决方案
如何将您的记录集分成“页”,而不用大型的结果?所谓页,基本上就是您指定应当显示在一起的许多记录。例如,如果您的记录集中有 100 条记录,可能每页显示 10 条记录。
ADO 提供了两种方法,PageSize 和 AbsolutePage。这些方法使您能够指定每页要显示的记录数,以及将游标定位于一页的开始。
打开记录集之后,基本步骤就是:
为该记录集指定 PageSize。它表示每页要显示的记录数。
指定该记录集的 AbsolutePage。这将记录指针移到页的序列中,给定页的开始处。
显示记录页。要完成这一步,您要用设置的 PageSize 次数循环整个记录集,或者直到到达文件的末尾。
示例代码
下列示例代码说明了页面建立过程。借助它,您可以建立自己的解决方案的原型。在您自己的代码中,确保要完成下列步骤:
添加错误处理。
添加对查询返回的记录数的限制。
用条件过滤记录。(如,建立 WHERE 子句)。
使用存储过程或视图。
一定要通过更改连接字符串和 SQL 语句来修改我的示例代码,以指向您的数据库。由于代码使用 ADO 常数,如 adUserServer,一定要在您的 Global.asa 文件中引用 ADO TypeLibrary,或在 ASP 页中包括 ADOVBS.INC 文件。请注意,在将项目引用设置为 Microsoft ADO 时,Visual InterDev(R) 会为您自动生成 TypeLibrary 引用。
注意该示例有两种方法可以提供导航栏:
ShowNavBar。 它为用户提供了带着记录计数一起跳到指定页的方法。为实现这一步,它使用了 RecordCount 和 PageCount 属性。
ShowNavBarFast。 该方法不提供跳转到指定页的能力,也不提供记录计数,但可以通过 CacheSize 属性控制取回的记录数。
PageThroughRs.Asp
<%@ Language=VBScript %>
<% Option Explicit %>
<SCRIPT LANGUAGE=VBScript RUNAT=SERVER>
'确保引用 ADO Typelib 或使用 ADOVBS.Inc
Dim iPageNum, iRowsPerPage
Main
Sub Main()
Dim rst
Dim sSQL, sConnString
If Request.QueryString("iPageNum") = "" Then
iPageNum = 1
Else
iPageNum = Request.QueryString("iPageNum")
iPageNum = CInt(iPageNum)
End If
iRowsPerPage = 10
sConnString = "Provider=SQLOLEDB.1;password=Xyz123;user id=WebUser;" & _
"Initial Catalog=NorthWind;Data Source=MySQLServer;" & _
"network=dbmssocn;"
'下列 SQL 从 SQL 视图中检索所有列。
'要优化性能:
'- 使用存储过程、视图或在 SELECT 中指定列
'- 使用限制返回的记录的条件(例如,WHERE 子句)
sSQL = "SELECT CategoryName, ProductName, QuantityPerUnit,"
sSQL = sSQL & "UnitsInStock, Discontinued"
sSQL = sSQL & " FROM [Products By Category]"
Set rst = GetRecords(sConnString, sSQL)
WriteTableHeader rst
WriteTableBody rst, iRowsPerPage, iPageNum
ShowNavBar rst
'ShowFastNavBar 方法不使用 RecordCount
'或 PageCount,所以它重试的记录数仅等于
'记录集的 CacheSize 指定的数量。
'ShowFastNavBar rst
CleanUp rst
End Sub
Function GetRecords(sConnString, sSQL)
Dim cnn
Dim rst
set cnn = Server.CreateObject("ADODB.CONNECTION")
cnn.ConnectionString = sConnString
nn.Open
Set rst = Server.CreateObject("ADODB.RECORDSET")
Set rst.ActiveConnection = cnn
'当记录集打开时,adUseClient 的 CursorLocation
' 将检索所有的记录。
'adUseServer 允许沿用 CacheSize
rst.CursorLocation = adUseServer
'在使用服务器端游标时,CacheSize
'限制了取回的行数。我们将只抓取正在显示的
'的记录的数目 - iRowsPerPage
rst.CacheSize = iRowsPerPage
rst.Open sSQL,,adOpenStatic, adLockReadOnly牋?
Set GetRecords = rst
end Function
Sub WriteTableHeader(rst)
Dim fld
Response.Write "<TABLE WIDTH=80% BORDER=1>"
Response.Write "<TR>"
'建立表的列标题
For Each fld in rst.Fields
Response.Write "<TD><B>" & fld.Name & "</B></TD>"
Next
Response.Write "</TR>"
End Sub
Sub WriteTableBody(rst, iRowsPerPage, iPageNum)
Dim iLoop
Dim fld
iLoop = 1
rst.PageSize = iRowsPerPage
rst.AbsolutePage = iPageNum
'写出记录的当前页
Do While (Not rst.EOF) and (iLoop <= iRowsPerPage)
Response.Write "<TR>"
For Each fld in rst.Fields
Response.Write "<TD>" & fld.value & "</TD>"
Next
iLoop = iLoop + 1
rst.MoveNext
Response.Write "</TR>"
Loop
Response.Write "</TABLE>"
End Sub
Sub ShowNavBar(rst)
Dim iPageCount
Dim iLoop
Dim sScriptName
'本版本提供了更丰富的用户导航,但是
'依赖于 RecordCount 和 PageCount,
'它抵消了为服务器端游标
'指定 CacheSize 的好处。
Response.Write "<BR><BR>"
sScriptName = Request.ServerVariables("SCRIPT_NAME")
If iPageNum > 1 Then
Response.Write " <a href=" & sScriptName & "?iPageNum="
Response.Write (iPageNum -1) & "><< Previous</a>"
End If
iPageCount = rst.PageCount
Do Until iLoop > iPageCount
f iLoop = iPageNum Then
Response.Write " <B>" & CStr(iLoop) & "</B>"
Else
Response.Write " <a href=" & sScriptName & "?iPageNum=" & _
Cstr(iLoop) & ">" & iLoop & "</a>"
End If
iLoop = iLoop + 1
Loop
If Not rst.EOF Then
Response.Write " <a href=" & sScriptName & "?iPageNum="
Response.Write (iPageNum +1) & "> Next >></a><BR>"
Else
Response.Write "<BR>"
End If
Response.Write "Page " & iPageNum & " of " & iPageCount & "<BR>"
Response.Write rst.RecordCount & " Records" 牋?
End Sub
Sub ShowFastNavBar(rst)
Dim iPageCount
Dim iLoop
Dim sScriptName
'在指定 CacheSize 和使用服务器端游标时,
'该方法特别有效,因为它不使用 RecordCount
'和 PageCount。需要用户具有经验。
&nb