如何在 SQL for MS Access 中实现分页?

Posted

技术标签:

【中文标题】如何在 SQL for MS Access 中实现分页?【英文标题】:How do I implement pagination in SQL for MS Access? 【发布时间】:2009-12-14 12:25:24 【问题描述】:

我正在使用 ASP.NET 通过 OdbcConnection 类访问 Microsoft Access 2002 数据库 (MDB),虽然速度很慢,但它运行良好。

我的问题是关于如何在 SQL 中为查询该数据库实现分页,因为我知道我可以将 TOP 子句实现为:

SELECT TOP 15 *
FROM table

但我无法找到一种方法将其限制为偏移量,这可以通过使用 ROWNUMBER 的 SQL Server 来完成。我最好的尝试是:

SELECT ClientCode,
    (SELECT COUNT(c2.ClientCode)
        FROM tblClient AS c2
        WHERE c2.ClientCode <= c1.ClientCode)
    AS rownumber
FROM tblClient AS c1
WHERE rownumber BETWEEN 0 AND 15

失败:

错误来源:Microsoft JET 数据库引擎

错误消息:没有为一个或多个必需参数指定值。

我无法解决此错误,但我假设它与确定 rownumber? 的子查询有关?

对此的任何帮助将不胜感激;我在谷歌上的搜索产生了无益的结果:(

【问题讨论】:

这个 Q 有 59 次观看(当时),我没有看到一个赞成票。这只是 DBA 的事情吗? 【参考方案1】:

如果您希望在 MS Acces 中应用分页,请使用此

SELECT *
FROM (
    SELECT Top 5 sub.ClientCode
    FROM (
        SELECT TOP 15 tblClient.ClientCode
        FROM tblClient
        ORDER BY tblClient.ClientCode
    ) sub
   ORDER BY sub.ClientCode DESC
) subOrdered
ORDER BY subOrdered.ClientCode

其中15是StartPos + PageSize,5是PageSize

编辑评论:

您收到的错误是因为您试图引用在同一级别的查询中分配的列名,即 rownumber。如果您要将查询更改为:

SELECT *
FROM (
    SELECT ClientCode,
           (SELECT COUNT(c2.ClientCode)
            FROM tblClient AS c2
            WHERE c2.ClientCode <= c1.ClientCode) AS rownumber                
    FROM tblClient AS c1
)
WHERE rownumber BETWEEN 0 AND 15

它不应该给你一个错误,但我不认为这是你想要的分页结果。

【讨论】:

谢谢!尽管由于 ODBC SQL 解析器,我仍然遇到了一些问题(请参阅我的答案)。 当然,是的 slaps head 我认为也可以使用 HAVING 子句,但我不确定 JET - 这就像尝试使用涂有损坏的 SQL玻璃。 @Codesleuth:每个数据库引擎都有自己的 SQL 方言。如果您想使用 Jet/ACE 作为后端,您需要学习它的 SQL 方言,而不是无理地期望它与您已经碰巧知道的任何 SQL 方言完全一样。我质疑基本设置的智慧,即在 Web 应用程序后面使用 Jet/ACE 数据存储。它可以很好地适用于大多数只读操作的小用户群,但无法扩展。 很明显,我使用 Access 数据库的原因是因为数据库引擎的选择超出了我的控制范围。我每天都是 SQL Server 程序员,这就是为什么这些差异让我发疯的原因。例如,链接 INNER JOIN 语句似乎需要在每组连接周围加上括号;我不明白为什么这是必要的,但我现在已经学会了,我可以从现在开始使用它。如果我按照自己的方式,这将完全在 SQL Server 中。数据库已经难以应付我们的 15 个用户,所以也许我会尽快更改它。 @Codesleuth:如果您使用的是特定的数据库引擎并且您对 SQL 方言的差异感到沮丧,那么问题出在您的不熟悉,而不是方言。【参考方案2】:

有关原始答案,请参阅 astander's answer,但这是我的最终实现,它考虑了一些 ODBC 解析器规则(跳过 30 条后的前 15 条记录):

SELECT *
FROM (
  SELECT Top 15 -- = PageSize
  *
  FROM
  (
   SELECT TOP 45 -- = StartPos + PageSize
   *
   FROM tblClient
   ORDER BY Client
  ) AS sub1
  ORDER BY sub1.Client DESC
 ) AS clients
ORDER BY Client

这里的区别在于,当按客户端名称排序时,我需要分页才能工作,并且我需要所有列(嗯,实际上只是一个子集,但我在最外层的查询中对其进行排序)。

【讨论】:

【参考方案3】:

我使用这段 SQL 代码来实现 Access 的分页

Select TOP Row_Per_Page * From [Select TOP (TotRows - ((Page_Number - 1) * Row_Per_Page)From SampleTable Order By ColumnName DESC] Order By ColumnName ASC

我发表了一篇带有一些截图的文章 on my blog

【讨论】:

【参考方案4】:

这是使用 OleDbDataAdapter 和 Datatable 类的简单分页方法。为简单起见,我使用了不同的 SQL 命令。

        Dim sSQL As String = "select Name, Id from Customer order by Id"
        Dim pageNumber As Integer = 1
        Dim nTop As Integer = 20
        Dim nSkip As Integer = 0
        Dim bContinue As Boolean = True
        Dim dtData as new Datatable
        Do While bContinue

            dtData = GetData(sSQL, nTop, nSkip, ConnectionString)

            nSkip = pageNumber * nTop
            pageNumber = pageNumber + 1

            bContinue = dtData.Rows.Count > 0
            If bContinue Then
                For Each dr As DataRow In dtData.Rows
                    'do your work here
                Next
            End If
        Loop

这里是 GetData 函数。

    Private Function GetData(ByVal sql As String, ByVal RecordsToFetch As Integer, ByVal StartFrom As Integer, ByVal BackEndTableConnection As String) As DataTable
    Dim dtResult As New DataTable
    Try
        Using conn As New OleDb.OleDbConnection(BackEndTableConnection)
            conn.Open()
            Using cmd As New OleDb.OleDbCommand
                cmd.Connection = conn
                cmd.CommandText = sql
                Using da As New OleDb.OleDbDataAdapter(cmd)
                    If RecordsToFetch > 0 Then
                        da.Fill(StartFrom, RecordsToFetch, dtResult)
                    Else
                        da.Fill(dtResult)
                    End If
                End Using
            End Using
        End Using
    Catch ex As Exception
    End Try
    Return dtResult
End Function

每次循环运行到文件末尾,上述代码都会从表 Customer 中返回 10 行。

【讨论】:

这是我正在寻找的解决方案 --> 使用 da 上的填充参数仅获取我需要的内容【参考方案5】:

在访问中使用限制或获取分页的一种简单方法是使用 ADODB 库,该库支持许多具有相同语法的数据库的分页。 http://phplens.com/lens/adodb/docs-adodb.htm#ex8 它很容易修改/覆盖寻呼机类,然后以数组格式获取所需的行数。

【讨论】:

【参考方案6】:
SELECT  *
FROM BS_FOTOS AS TBL1
WHERE ((((select COUNT(ID) AS DD FROM BS_FOTOS AS TBL2 WHERE TBL2.ID<=TBL1.ID)) BETWEEN  10 AND 15 ));

它的结果只有 10 到 15 条记录。

【讨论】:

以上是关于如何在 SQL for MS Access 中实现分页?的主要内容,如果未能解决你的问题,请参考以下文章

MS Access SQL 将行转换为列

如何在 vb.net 中实现交易方式?

从现有的 MS Access 表自动生成 SQL

如何在 Access 2003 中实现版本控制?

MS-Access ODBC 连接到 Oracle for SQL

如何在SQL 2005中实现循环每一行做一定的操作