Skip to content

分页功能

本文档详细介绍 cDataBase 类的分页查询功能,支持 SQL Server、MySQL、Access 等数据库。


? 目录


分页概述

什么是分页

分页是将大量数据分成多个页面显示的技术,每页显示固定数量的记录。

分页的优势

  • 性能优化 - 只查询需要的数据,减少内存占用
  • 用户体验 - 快速加载,避免长时间等待
  • 资源节约 - 减少网络传输和数据库负载

分页原理

cDataBase 的分页功能使用 ADO 原生分页属性Rs.PageSizeRs.AbsolutePage)实现,不修改 SQL 语句。这意味着:

  • 分页对所有数据库类型(SQL Server、MySQL、Access、CSV)均有效
  • 无需针对不同数据库编写不同的分页 SQL
  • 需要使用支持 AbsolutePage 的游标类型(如 adOpenKeyset
总记录数: 1000
每页显示: 10
总页数: 100

第 1 页: Rs.AbsolutePage = 1, Rs.PageSize = 10
第 2 页: Rs.AbsolutePage = 2, Rs.PageSize = 10
第 3 页: Rs.AbsolutePage = 3, Rs.PageSize = 10
...

Page 方法

语法

vb
Function Page(Optional num As Long = 1, Optional Limit As Long = 10) As cDataBase

参数说明

参数类型说明
numLong页码(可选,默认 1)
LimitLong每页记录数(可选,默认 10)

返回值

返回 cDataBase 对象,支持链式调用。

示例

vb
' 查询第 1 页,每页 10 条
db.Sql("SELECT * FROM users").Page(1, 10).Query

' 查询第 2 页,每页 20 条
db.Sql("SELECT * FROM users").Page(2, 20).Query

支持的数据库

分页使用 ADO 原生分页属性实现,所有数据库类型通用,无需针对不同数据库编写不同的 SQL。

实现原理

Page 方法设置分页参数后,QueryFetch 方法在打开 Recordset 后自动应用:

vb
' 内部实现(源码)
Rs.Open pvRawSqlString, Conn, CurType, LockType, Options
If IsPage Then
    Rs.PageSize = pvPageLimit       ' 设置每页记录数
    Rs.AbsolutePage = pvPageNum     ' 设置当前页码
    IsPage = False
End If

注意事项

  1. 游标类型要求:分页需要使用支持 AbsolutePage 的游标类型(默认 adOpenKeyset 即可支持)
  2. 不建议使用 adOpenForwardOnly:仅向前游标不支持 AbsolutePage,分页将无法正常工作
  3. SQL 语句不变:分页不会修改原始 SQL,SQL 保持原样执行,分页由 ADO 在 Recordset 层面处理

使用示例

示例 1:基本分页

vb
' 查询第 1 页,每页 10 条
If db.Sql("SELECT * FROM users").Page(1, 10).Fetch Then
    Dim i As Long
    For i = 1 To db.Rows.Count
        Debug.Print db.Rows(i)("name")
    Next
End If

示例 2:带排序的分页

vb
' 按年龄降序排列,分页显示
If db.Sql("SELECT * FROM users ORDER BY age DESC").Page(2, 10).Fetch Then
    Dim i As Long
    For i = 1 To db.Rows.Count
        Debug.Print db.Rows(i)("name") & " - " & db.Rows(i)("age")
    Next
End If

示例 3:条件查询分页

vb
' 查询年龄大于 18 的用户,分页显示
If db.Sql("SELECT * FROM users WHERE age > 18").Page(1, 20).Fetch Then
    Dim i As Long
    For i = 1 To db.Rows.Count
        Debug.Print db.Rows(i)("name")
    Next
End If

示例 4:获取总记录数

vb
' 查询总数
Dim lTotal As Long
lTotal = db.Count("users")

' 计算总页数
Dim lPageSize As Long
lPageSize = 10
Dim lTotalPages As Long
lTotalPages = Int((lTotal + lPageSize - 1) / lPageSize)

' 分页查询
If db.Sql("SELECT * FROM users").Page(1, lPageSize).Fetch Then
    ' 显示数据
End If

示例 5:完整分页函数

vb
' 分页查询函数
Function GetUsersPage(lPage As Long, lPageSize As Long) As Collection
    Set GetUsersPage = New Collection

    ' 查询数据
    If db.Sql("SELECT * FROM users ORDER BY id").Page(lPage, lPageSize).Fetch Then
        Set GetUsersPage = db.Rows
    End If
End Function

' 使用
Dim colUsers As Collection
Set colUsers = GetUsersPage(1, 10)

示例 6:分页导航

vb
' 分页导航类
Private m_lCurrentPage As Long
Private m_lPageSize As Long
Private m_lTotalRecords As Long

Private Sub LoadPage(lPage As Long)
    ' 验证页码
    If lPage < 1 Then lPage = 1

    Dim lTotalPages As Long
    lTotalPages = Int((m_lTotalRecords + m_lPageSize - 1) / m_lPageSize)
    If lPage > lTotalPages Then lPage = lTotalPages

    m_lCurrentPage = lPage

    ' 查询数据
    If db.Sql("SELECT * FROM users ORDER BY id").Page(lPage, m_lPageSize).Fetch Then
        ' 显示数据
        DisplayUsers
    End If
End Sub

Private Sub cmdNextPage_Click()
    LoadPage m_lCurrentPage + 1
End Sub

Private Sub cmdPrevPage_Click()
    LoadPage m_lCurrentPage - 1
End Sub

性能优化

1. 使用索引字段排序

vb
' ? 推荐:使用索引字段排序
db.Sql("SELECT * FROM users ORDER BY id").Page(1, 10).Query

' ? 不推荐:使用非索引字段排序
db.Sql("SELECT * FROM users ORDER BY name").Page(1, 10).Query

2. 只查询需要的字段

vb
' ? 推荐:只查询需要的字段
db.Sql("SELECT id, name FROM users").Page(1, 10).Query

' ? 不推荐:查询所有字段
db.Sql("SELECT * FROM users").Page(1, 10).Query

3. 使用 WHERE 条件限制

vb
' ? 推荐:使用 WHERE 条件
db.Sql("SELECT * FROM users WHERE status = 'active'").Page(1, 10).Query

' ? 不推荐:查询所有数据再分页
db.Sql("SELECT * FROM users").Page(1, 10).Query

4. 合理设置每页记录数

vb
' ? 推荐:合理的每页记录数(10-50)
db.Sql("SELECT * FROM users").Page(1, 20).Query

' ? 不推荐:每页记录数过大
db.Sql("SELECT * FROM users").Page(1, 1000).Query

常见问题

Q1: 分页后 RecordCount 返回 -1

原因: 使用了 adOpenForwardOnly 游标类型,不支持 RecordCountAbsolutePage

解决:

  • 使用 adOpenKeysetadOpenStatic 游标类型(默认即是 adOpenKeyset
  • 分页查询不建议使用 adOpenForwardOnly

Q2: 分页时 AbsolutePage 设置失败

原因: 游标类型不支持 AbsolutePage 属性。

解决:

  • 确保使用 adOpenKeyset(默认)或 adOpenStatic 游标类型
  • 检查 SQL 语句是否正确执行并返回结果

Q3: 如何获取总记录数?

vb
' 方法 1:使用 Count 方法
Dim lTotal As Long
lTotal = db.Count("users")

' 方法 2:使用 COUNT(*) 查询
If db.Sql("SELECT COUNT(*) AS cnt FROM users").Fetch Then
    lTotal = db.Row("cnt")
End If

Q4: 分页后如何保持排序?

vb
' ? 正确:在 SQL 中包含 ORDER BY
db.Sql("SELECT * FROM users ORDER BY age DESC").Page(1, 10).Query

' ? 错误:分页后再排序(会丢失排序)
db.Sql("SELECT * FROM users").Page(1, 10).Query
' 然后对结果排序(只对当前页排序,不是全局排序)

Q5: 如何实现跳转到指定页?

vb
Function GoToPage(lPage As Long, lPageSize As Long) As Boolean
    ' 验证页码
    If lPage < 1 Then lPage = 1

    ' 查询指定页
    If db.Sql("SELECT * FROM users ORDER BY id").Page(lPage, lPageSize).Fetch Then
        GoToPage = True
    Else
        GoToPage = False
    End If
End Function

最佳实践

1. 始终使用 ORDER BY

vb
' ? 推荐:使用 ORDER BY 保证顺序
db.Sql("SELECT * FROM users ORDER BY id").Page(1, 10).Query

' ? 不推荐:不使用 ORDER BY(顺序不确定)
db.Sql("SELECT * FROM users").Page(1, 10).Query

2. 验证页码和每页记录数

vb
' ? 推荐:验证参数
Function GetPage(lPage As Long, lPageSize As Long) As Collection
    If lPage < 1 Then lPage = 1
    If lPageSize < 1 Then lPageSize = 10
    If lPageSize > 100 Then lPageSize = 100  ' 限制最大每页记录数

    If db.Sql("SELECT * FROM users ORDER BY id").Page(lPage, lPageSize).Fetch Then
        Set GetPage = db.Rows
    End If
End Function

3. 缓存总记录数

vb
' ? 推荐:缓存总记录数,避免频繁查询
Private m_lCachedTotal As Long
Private m_dtCacheTime As Date

Function GetTotalRecords() As Long
    ' 缓存 5 分钟
    If DateDiff("s", m_dtCacheTime, Now) > 300 Or m_lCachedTotal = 0 Then
        m_lCachedTotal = db.Count("users")
        m_dtCacheTime = Now
    End If
    GetTotalRecords = m_lCachedTotal
End Function

最后更新: 2026-01-21

VB6及其LOGO版权为微软公司所有