【问题标题】:How does Access 2007's moveNext/moveFirst/, etc., feature work?Access 2007 的 moveNext/moveFirst/ 等功能如何工作?
【发布时间】:2010-05-06 15:09:40
【问题描述】:

我不是 Access 专家,但我是 SQL 专家。我继承了一个 Access 前端,它引用了一个 SQL 2005 数据库,该数据库对大约 5000 条记录运行良好,但对于 80 万条记录却惨遭失败......

在 SQL 分析器和活动管理器的幕后,我看到了某种 Access 查询,例如:

SELECT "MS1"."id" FROM "dbo"."customer" "MS1" ORDER BY "MS1"."id"

MS 前缀没有出现在我能看到的任何访问代码中。我对内置的 Access 导航代码持怀疑态度:

DoCmd.GoToRecord , , acNext

GoToRecord 有 AcRecord 常量,包括 acFirst、acLast、acNext、acPrevious 和 acGoTo。

在数据库上下文中移动到“下一个”记录是什么意思?这个特定的表使用一个标识列作为 PK,所以它是在内部抓取 所有 ID,然后移动到下一个最高的那个???

如果是这样,如果一个表由三个不同的 PK 字段组成,它将如何工作?

还是我走错了路,Access 中的其他东西正在调用该语句?不幸的是,我在分析器中看到了大量准备好的语句。

谢谢!

【问题讨论】:

    标签: sql ms-access vba


    【解决方案1】:

    First 实际上是 Recordset 中的第一行。通常,Access 通过相当于游标的方式访问数据。因此,Next 和Previous 在 Recordset 中一次向前和向后移动一行,就像使用 SQL Server 的游标一样。在构造 Recordset 时要小心依赖没有 ORDER BY 语句的行的顺序。尽管 Access 是一个 ISAM,但您不应依赖以任何特定顺序出现的行。根据游标类型,Access 不会拉下整个表,但通常会一次要求一条记录。也就是说,我已经看到 Access 出于某种原因拉取了整个表。

    【讨论】:

    • 愚蠢的字符限制!这个应用程序不是很复杂——只有五个左右的表,但一个表中大约有 300k 条记录,另一个表中大约有 800k 条记录。该应用程序基本上允许对记录进行简单的编辑。如果我们使用光标,多用户编辑如何工作?似乎 Access 的行为适当,每次有机会动态刷新主键 (PK) 列表。如何指定游标类型?这里没有记录集。相反,我认为 Access 只是指向整个表。
    • @Chris M - RE:多用户编辑,我们是在谈论前端/后端所有 Access 配置、具有链接表到真实 DBMS 的 Access 前端,还是具有真正的数据库管理系统?通常,RS 的打开方式决定了锁的设置方式。如果 RS 是使用 adLockOptimistic 打开的,Access 将在保存期间锁定记录。如果设置为 adLockPessimistic,它将在记录被编辑时锁定记录。标准表单通常会在编辑期间锁定行。在 ADP 设置中,我认为它只是基于 PK 进行更新,但使用游标从一行循环到下一行。
    • 前端 Access 2007,后端 SQL 2005 通过 ODBC。该应用程序几乎可以互换使用 adLockOptimistic 和 adLockPessimistic。我怀疑作者是否知道其中的区别。最糟糕的部分是我认为这里真正的问题是固有控件提供的记录集导航。不知何故,我需要防止 Access 反复带回主键。我认为最终我会修改应用程序以通过存储过程完全加载数据并断开与 SQL 表的连接。我会自己处理所有的导航。谢谢!
    【解决方案2】:

    您必须区分自动化 Access 对象和使用代码中的记录集。

    在一个表格中,这个命令有含义:

      DoCmd.GoToRecord , , acNext
    

    它是非特定的,除非您知道表单中基础记录集的顺序和起始记录,否则无法预测它将转到哪条记录。它引导您浏览存储在表单编辑缓冲区(在表单的 OnOpen 事件中加载)中的记录集。例如,该命令将用于命令按钮后面的代码中,其目的是导航加载到当前具有焦点的表单中的记录。如果我要使用该命令,我永远不会遗漏可选参数(我几乎从不这样做)。相反,我会确定我希望它应用到的特定表单:

      DoCmd.GoToRecord acForm, "MyForm", acNext
    

    在遍历 DAO 记录集时,.MoveNext 同样没有预定义的含义,除非您知道排序和起始记录。当你在遍历一个记录集(你不应该经常做的事情,因为它效率很低;但这取决于你需要执行的任务)并且需要点击每条记录时,你肯定会调用 .MoveNext 作为你的一部分循环:

      With rs
        .MoveFirst ' technically not required, as it's the default starting point
        Do Until .EOF
          [do something]
          .MoveNext     
        Loop
      End With
    

    那里没有什么神秘的。它最有可能用于记录数量较少的代码中(大型记录集确实不应该按顺序导航)。

    回答您的具体问题:

    在数据库中是什么意思 上下文移动到“下一个”记录? 此特定表使用标识 列作为PK,内部也是如此 抓住所有的身份证然后移动 到次高的那个???

    ...正如我所说,下一条记录由被遍历的记录集的顺序和起始位置决定。在表单的情况下,它是被遍历的编辑缓冲区,并且随着编辑缓冲区中当前记录书签的更改,表单被更新以加载该记录的数据。动态集绑定到底层数据表,当保存表单的编辑缓冲区时,将编辑后的数据写回服务器。在编辑时,服务器上的记录可能会或可能不会保持锁定,但 Access/Jet/ACE 会跟踪服务器上现有记录的状态和编辑缓冲区中的记录,并会在如果服务器上的记录在加载到表单的编辑缓冲区后发生更改,则可以在 Access 中节省时间。

    现在,在评论中,您说表单绑定到整个表格。无论您的数据是存储在 Jet/ACE 后端数据文件中还是存储在 SQL Server 等服务器数据库中,这都是一个糟糕的设计。 Access 可以摆脱它的唯一原因是它和 Jet 在从数据源中提取数据方面相当有效。

    我设计合理的客户端/服务器 Access 前端不会在表单中加载完整的表,而是询问您要加载的过滤记录集,一次可以加载 1 个或多个记录。这仅比绑定到整个表稍微复杂一点。

    至于知道正在使用的游标类型,您不必担心。默认情况下,Access 表单使用 Access/Jet/ACE 所称的动态集。每个表单都有一个 RecordsetType 属性,默认设置为 dynaset(阅读帮助文件了解不同记录集类型的含义)。如果您想要更多地控制它,您可以(但可能不应该)在代码中创建您的记录集并将它们分配给表单的 .Recordset 属性。这在某些情况下很有用,例如当您想将表单绑定到断开连接的记录集时,但 Access 的重点是利用其处理绑定数据的功能。分配您自己的记录集仍然可以让您绑定控件和表单事件,但工作量比通常需要的要多。

    基本上,将您的表单更改为仅加载用户需要使用的记录子集(一次可能只有一条记录),然后让其他所有操作都使用 Access 的默认行为完成。如果某事导致了瓶颈,则对其进行故障排除并用更有效的方法替换默认行为。

    换句话说,避免过早的优化——让 Access 成为 Access。

    不要担心 Access 在幕后做了什么,除非/直到 Access 做了不恰当的事情。

    【讨论】:

    • @David - 感谢您的建议和良好的信息。是的,这是一个非常糟糕的 POS。大量的 goto、未定义的变量、糟糕的数据库设计。例如,邮政编码是浮点数。表单绑定到整个表格。因此,当用户从一个记录导航到另一个记录时,Access 似乎(来自 SQL Profiler)正在从一个巨大的表中获取主键的整个列表。我的关键问题是如何阻止这种行为。谢谢!
    • @David - 另外,我问的原因是 Access 需要 8 秒以上才能从表中的一条记录移动到下一条记录。我相信这是因为每次用户导航到表中的新记录时,都会有 200k 到 800k 的整数(表的主键)从后端 SQL 数据库传递回前端 Access。这是在一个足够强大的服务器上,能够处理正确设计的更大数量级的数据库(但没有 Access 前端垃圾)。
    • 我有点惊讶 Jet 会提取这么多数据。我一直认为 Jet 会像使用自己的数据文件一样对 ODBC 数据源使用类似 Rushmore 的“惰性”检索。我不知道,因为我从未将 Access 表单绑定到整个 SQL Server 表。我只对带有 Jet/ACE 后端的小桌子这样做。
    • 您对导航缓慢的猜测对我来说听起来很奇怪(但是,我从未将 Access 表单绑定到整个 SQL Server 表)。表单的排序顺序是否与 SQL Server 表上的聚集索引不同?如果是这样,您可以尝试对表单用于排序顺序的索引进行聚类,或者使用表单的排序顺序创建索引视图,然后链接到该索引而不是基表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多