【问题标题】:How do I implement pagination in SQL for MS Access?如何在 SQL for MS Access 中实现分页?
【发布时间】:2010-12-26 10:00:46
【问题描述】:

我正在使用 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 的事情吗?

标签: sql ms-access pagination


【解决方案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】:

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

      【讨论】:

        【解决方案5】:

        这是使用 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 上的填充参数仅获取我需要的内容
        【解决方案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 条记录。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-25
          • 1970-01-01
          • 2014-03-21
          • 1970-01-01
          • 2019-01-21
          相关资源
          最近更新 更多