MS Access 2010:“无法打开更多数据库。”

8

在处理一个老旧的MS Access应用程序时,我遇到了这个奇怪的错误:

Cannot open any more databases.

该应用程序广泛使用UNION SQL语句。因此,这似乎会导致访问命中2048个打开表的限制。是否有其他方法除了摆脱这些联合?


3
哇,2048张桌子...出于好奇,事情怎么会变得如此糟糕? - Kieren Johnstone
尽管Kieren的观点很出色,但我很惊讶提供的答案中没有更多倾向于认真重新思考UNION SQL的。如果数据结构得到了良好的优化,那么你永远不应该需要最终得到如此庞大的查询。在Access中尤其糟糕,因为所有操作都在本地运行,可能需要一辈子才能完成。 - Matt Donnan
1
是的,联合体是一种特殊情况,90%的时间被新手用来执行简单任务,最终会生成大量数据集,在他们离开后,这些数据集变得不可靠,并且如果使用不当,则信息返回也会随着时间的推移不可靠。 - GoldBishop
性能提示:如果您要连接的查询没有重复项需要删除,则UNION ALLUNION更快且使用的开销更少。 - Ben
是的,大多数联合使用了ALL。但这并不能解决打开“数据库”的数量问题(无论哪种方式)。 - Christian
显示剩余2条评论
6个回答

4

使用外部链接表时,我遇到了这个问题。由于大约有10个Excel文件被不同的查询一遍又一遍地使用,因此打开的表的数量更多或更少是查询和表的乘积。

我想联合查询也会加剧这个问题。

对我来说,解决办法是先将链接的Excel表复制到Access本地表中,然后使用本地表运行完全相同的查询。


德语消息是 Fehler 3048: Mehr Datenbanken können nicht geöffnet werden - msjav
哇,这样编辑和执行查询的速度快了好几个数量级。有点糟糕的是Access不能自己处理这个。但对于我的情况来说,这个解决方案还可以。 - Christian

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

此更改有其他好处。您的表单将加载更快,并且记录导航将更快。


实际上没有涉及到表单或VBA代码。只需打开accdb并执行一个(特定的)查询即可弹出错误消息。如果将依赖查询的结果放入表格中,并使用修改后的查询版本,它就可以工作了。 - Christian
您的查询可能调用聚合或VBA函数。您能发布此查询的SQL吗?您提到了特定的查询。仅适用于此查询吗?还是其他查询也适用? - ricardohzsz
查询的代码类似于SELECT * FROM A UNION ALL SELECT * FROM B... - 但是msjav的答案很好地解决了实际问题。 - Christian

2
您需要评估 UNION 查询的每个部分以及它所依赖的任何其他查询。创建一个代表具有多个连接表的查询的临时表,并使用该临时表可能会提高性能。

当我开始使用 Access 进行开发时,我有一个习惯,即制作大型非规范化的 snowflake 查询,并将它们用作报表和列表框的数据源。我的数据库中没有超过 100,000 条记录的表,因此数据库运行速度很快。后来,我开始遇到令人烦恼的“无法打开更多数据库”错误,并发现了我的错误。

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

enter image description here

请注意,对本地表或查询对象的每个引用都使用1个连接。对链接表的引用使用2个连接。连接两个链接表的查询将使用5个连接。如果该查询被您的 union 中的许多其他查询调用,则数字会快速增加。也许您在子查询中不需要联接表中的任何字段。在这种情况下,您可以创建一个新的查询。
我在网上读到了很多关于此事的信息,有些人认为Access/Jet大约有2,000个TableID,但这个数字与我的表单报告不符。我的表单报告的数字与错误完全对应。它可能计算了与TableID不同的东西,但是它提供了一个准确的衡量连接数量的方法,当您打开新对象时。
您可以从这里阅读更多并下载:

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


您可以在此处下载我的可用连接实用程序的更新版本:http://www.mendipdatasystems.co.uk/available-connections/4594418530。 - Ben
1
非常感谢提供“可用连接”实用程序。这将帮助我理解在复杂的Access UI中遇到的许多奇怪行为。 - SAL

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

End Sub


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

哦,我之前没有理解这个答案。我猜你的意思和msjav一样? - Christian
是的,但我的回答不太清楚...应该真正使用例子,我将在未来包含例子以帮助 :) - twoleggedhorse

0

您的应用程序尝试打开太多连接到Access数据库。不仅是您SQL语句中的表达式总数达到了2048,甚至包括表单、报表、组合框、未关闭的记录集等也会增加应用程序使用的连接数。以下是您可以尝试的几件事情:
1. 关闭您实际上没有使用的资源(例如记录集)。
2. 如果您正在使用域聚合函数(例如DLookup),请改用Elookup,因为它会明确地在自身清理后进行清理。
3. 您可以修改您的SQL代码以使用Temp Tables。
希望这有所帮助。


关闭资源没用,我猜测。我可以启动应用程序,执行一个查询(没有vba),然后错误就会出现。临时表怎么能帮助呢?你能举个例子吗? - Christian

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