8

在处理单个遗留 MS Access 应用程序时,我遇到了这个奇怪的错误:

Cannot open any more databases.

该应用程序广泛使用UNIONsql 语句。所以这似乎导致访问达到 2048 个打开表的限制。除了摆脱这些工会还有其他机会吗?

4

6 回答 6

4

我在使用链接的外部表时遇到了这个问题。已达到限制,因为不同的查询一遍又一遍地使用了大约 10 个 excel 文件。所以打开表的数量或多或少是查询和表的乘积。

我想使用工会也会增加这个问题。

我的解决方案是先将链接的 excel 表复制到 Access 本机表中。然后使用本机表运行相同的查询。

于 2012-09-25T13:40:46.107 回答
3

通常,这发生在具有许多子表单和/或组合框/列表框的大/复杂表单中。

尝试按照 Saurabh 所说的去做。反正都是好东西。但我认为这些更改不会解决您的问题。

最近,我解决了同样的问题。我发现在打开给定表单时总是会发生这种情况。这种形式有许多子形式和组合。

第一的。尝试使您的表单或表单更简单:您真的需要所有子表单吗?必须始终加载所有子表单?

我解决了在选项卡控件的不同页面中分配子表单的问题。然后在 Change 事件中动态加载和卸载子表单。

最初,只有第一页上的子表单必须分配“SourceObject”属性。其余的,此属性为空。

在更改事件中,尝试执行以下操作:

Private Sub TabControl_Change
    Dim pgn As Access.Page
...
    For Each varCtlSubform In Array(Me.Subform1, Me.Subform1, ...)
        Set pgn = varCtlSubform.Parent
        If pgn.PageIndex <> Me.TabControl.value Then
            if varCtlSubform.SourceObject <> "" Then
                varCtlSubform.SourceObject = ""
            End if
        Else
            If varCtlSubform.SourceObject <> ctlSubform.Tag then
                varCtlSubform.SourceObject = ctlSubform.Tag
            End if
        End If
    Next
...
End sub

这是一个迭代所有子窗体控件的通用函数。如果不在活动页面中,请将其卸载。在其他情况下,从标签属性中获取源对象。

您需要避免引用已卸载的子表单,即,如果“Subform1”已卸载,您将收到类似以下内容的错误:Me.Subform1.Form.InvoiceId

这种变化还有其他好处。您的表单将加载更快,记录导航将更快。

于 2012-09-25T10:50:21.113 回答
2

您需要评估 UNION 查询的每个部分以及它所依赖的任何其他查询。您可以通过创建一个表示具有许多连接表的查询的临时表来获得改进,并改用该临时表。

当我开始使用 Access 进行开发时,我习惯于进行大型非规范化雪花查询并将它们用作报告和列表框的来源。我没有任何超过 100,000 条记录的表,并且数据库运行得很快。后来我开始收到烦人的“无法打开更多数据库”错误,并发现了我的方式的错误。

我创建了一个表单,可以帮助跟踪您使用了多少数据库连接以及剩余多少。如果您将此表单添加到数据库并在打开查询和其他对象后单击重新查询,您将能够找到使用大量连接的对象。

在此处输入图像描述

请注意,对本地表或查询对象的每个引用都使用 1 个连接。对链接表的引用使用 2 个连接。连接两个链接表的查询将使用 5 个连接。如果您的联合中的许多其他查询都调用了该查询,则该数字加起来很快。也许您不需要子查询中连接表中的任何字段。在这种情况下,您可以进行新查询。

我在网上阅读了很多关于此的内容,有些人认为 Access/Jet 有大约 2,000 个 TableID,但这个数字与我的表单报告的不匹配。我的表格报告的数字与错误完全一致。它可能会计算与 TableID 不同的东西,但它提供了一个准确的计量器来测量您打开新对象时使用的连接数量。

您可以阅读更多内容并从此处下载:

https://access.wordpress.com/2014/04/01/how-many-database-connections-are-still-available-in-an-access-database/

于 2018-11-02T19:53:03.817 回答
1

我要感谢ricardohzsz的精彩代码!它确实帮助我提高了数据库性能并消除了错误 3048。

我会投票支持该帖子,但我在这里没有足够的声誉来投票。

我必须进行一些修改才能使其满足我的需要(我需要子表单来允许添加和编辑,并且使用此代码使它们成为只读的)。我在这里发布更改,以防它也可以帮助其他人:

Private Sub TabControlMain_Change()

Dim pgn As Access.Page
Dim sbf As SubForm
Dim strSubForm As String
Dim VarCtlSubform As Variant


For Each VarCtlSubform In Array(Me.sf1, Me.sf2, Me.sf3, etc) 
Set pgn = VarCtlSubform.Parent
    If pgn.PageIndex <> Me.TabControlMain.Value Then
        If VarCtlSubform.SourceObject <> "" Then
            VarCtlSubform.SourceObject = ""
        End If
    Else

        If VarCtlSubform.SourceObject <> VarCtlSubform.Tag Then
            VarCtlSubform.SourceObject = VarCtlSubform.Tag

            strSubForm = VarCtlSubform.Name
            Set sbf = Screen.ActiveForm.Controls(strSubForm)
            sbf.Form.AllowAdditions = True
            sbf.Form.AllowEdits = True
        End If
    End If
Next

结束子

于 2015-03-10T18:17:44.957 回答
1

解决此问题的唯一真正方法是使用一组临时表。将联合的结果插入到临时表中,然后使用它们来限制每个查询的表数。我通常在我的临时表前加上下划线 (_tmpCustomers),然后在完成后销毁它们。

于 2012-09-25T09:02:40.947 回答
0

您的应用程序正试图打开太多与 Access 数据库的连接。不仅仅是你的 sql 语句中的表加起来为 2048,甚至表单、报告、组合框、未关闭的记录集等加起来就是你的应用程序使用的连接数。您可以在这里尝试的几件事:
1. 关闭您没有真正使用的资源(例如记录集)。
2. 如果您正在使用域聚合函数(例如 DLookup),请使用 Elookup 更改它,因为它会在自身之后显式清理。
3.您可以修改您的sql代码以使用临时表。
希望能帮助到你。

于 2012-09-25T09:07:55.653 回答