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

12

我正在使用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 数据库引擎

错误信息: 一个或多个必需的参数未提供值。

我无法解决这个错误,但我猜想它可能与用于确定行号的子查询有关?

非常感谢您的帮助;我在谷歌上的搜索结果并没有什么帮助:(


这个问题目前已经有59次浏览,但我没有看到任何一次点赞。这只是DBA的事情吗? - Adriaan Stander
7个回答

12

如果您希望在MS Access中应用分页,请使用以下方法

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解析器(请参见我的答案)。 - Codesleuth
1
当然,是的 拍头 我想也可以使用HAVING子句,但我不确定JET是否支持 - 这就像尝试使用涂有碎玻璃的SQL进行工作。 - Codesleuth
@Codesleuth:每个数据库引擎都有自己的SQL方言。如果你想使用Jet/ACE作为后端,你需要学习它的SQL方言,而不是不合理地期望它与你已经知道的任何SQL方言完全相同。我对基本设置的智慧提出质疑,即在Web应用程序后面使用Jet/ACE数据存储。它可以很好地适用于小用户群体的大多数只读操作,但无法扩展。 - David-W-Fenton
1
“(勉强)不明说我故意编写代码来限制我的客户只使用Access的暗示令我感到冒犯,但这在你这样的人身上并不令人意外。” - David-W-Fenton
1
@Codesleuth:如果你在使用特定的数据库引擎,并且因为SQL方言的差异而感到沮丧,那么问题不在于方言,而在于你对其不熟悉。 - David-W-Fenton
显示剩余3条评论

4
请参考astander的答案来查看原始回答,但这里是我的最终实现,考虑了一些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

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

2

这是使用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行,直到文件结束。

1
这就是我正在寻找的解决方案 --> 使用da上的填充参数仅获取我所需的内容。 - Missy

2
我使用这段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
我在我的博客上发布了一篇文章,其中包含一些截图:Implementation of SQL Pagination with MS Access

0
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条记录。


0

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


-2

我觉得之前的回答有些过于复杂了。

一个派生表格内嵌另一个派生表格。

我认为这个语法可以满足你的需求。

SELECT * FROM tblClient ORDER BY Client OFFSET 30 ROWS FETCH NEXT 15 ROWS ONLY


1
这个问题涉及到MS Access,你的回答不是Access SQL。 - Andre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接