単一のレガシーMSAccessアプリケーションで苦労しているときに、この奇妙なエラーに直面しました。
Cannot open any more databases.
アプリケーションはUNION
SQLステートメントを広範囲に使用します。したがって、これにより、アクセスが2048のオープンテーブルの制限に達するように見えます。これらの組合を取り除く以外のチャンスはありますか?
単一のレガシーMSAccessアプリケーションで苦労しているときに、この奇妙なエラーに直面しました。
Cannot open any more databases.
アプリケーションはUNION
SQLステートメントを広範囲に使用します。したがって、これにより、アクセスが2048のオープンテーブルの制限に達するように見えます。これらの組合を取り除く以外のチャンスはありますか?
リンクされた外部テーブルを使用すると、この問題が発生しました。さまざまなクエリで約10個のExcelファイルが何度も使用されたため、制限に達しました。したがって、開いているテーブルの数は、多かれ少なかれクエリとテーブルの積でした。
ユニオンを使用すると、この問題も倍増すると思います。
私にとっての解決策は、最初にリンクされたExcelテーブルをAccessネイティブテーブルにコピーすることでした。次に、ネイティブテーブルを使用してまったく同じクエリを実行します。
多くの場合、これは、多くのサブフォームやコンボボックス/リストボックスを含む大きな/複雑なフォームで発生します。
Saurabhが言うことをやってみてください。とにかく良いことです。しかし、これらの変更はあなたの問題を解決しないと思います。
最近、私は同じ問題を解決します。特定のフォームが開かれたときに常に発生することを確認しました。このフォームには多くのサブフォームとコンボがありました。
初め。1つまたは複数のフォームを単純化してみてください。本当にすべてのサブフォームが必要ですか?すべてのサブフォームは常にロードする必要がありますか?
タブコントロールのさまざまなページにサブフォームを配布する際の問題を解決します。次に、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
この変更には他にも利点があります。フォームの読み込みが速くなり、レコードのナビゲーションが速くなります。
UNIONクエリの各セクション、およびそれが依存するその他のクエリを評価する必要があります。多くの結合テーブルを含むクエリを表す一時テーブルを作成し、代わりに一時テーブルを使用することで、改善が得られる場合があります。
Accessで開発を始めたとき、私は大きな非正規化スノーフレーククエリを作成し、それらをレポートとリストボックスのソースとして使用する習慣がありました。100,000を超えるレコードを持つテーブルがなく、データベースは高速に実行されました。その後、「これ以上データベースを開くことができません」という厄介なエラーが発生し始め、自分のやり方のエラーを発見しました。
使用したデータベース接続の数と残りのデータベース接続の数を追跡するのに役立つフォームを作成しました。このフォームをデータベースに追加し、クエリやその他のオブジェクトを開いた後で[再クエリ]をクリックすると、多数の接続を使用しているオブジェクトを見つけることができます。
ローカルテーブルまたはクエリオブジェクトへのすべての参照は1つの接続を使用することに注意してください。リンクされたテーブルへの参照は2つの接続を使用します。2つのリンクされたテーブルを結合するクエリは、5つの接続を使用します。そのクエリがユニオン内の他の多くのクエリによって呼び出されている場合、その数は急速に増加します。サブクエリで結合されたテーブルのフィールドは必要ないかもしれません。その場合、新しいクエリを作成できます。
私はこれについてオンラインでたくさん読んでおり、Access / Jetには約2,000のTableIDがあると考える人もいますが、その数は私のフォームのレポートと一致しません。私のフォームによって報告された数値は、エラーと完全に一致しています。TableIDとは異なるものをカウントしている可能性がありますが、新しいオブジェクトを開くときに使用されている接続の量を測定するための正確なゲージを提供します。
あなたはもっと読んで、ここからそれをダウンロードすることができます:
この問題を回避する唯一の実際の方法は、テーブルの一時的なセットを使用することです。ユニオンからの結果を一時テーブルに挿入し、それらを使用してクエリごとのテーブルの数を制限します。私は通常、一時テーブルの前にアンダースコア(_tmpCustomers)を付け、完了したらそれらを破棄します。
彼の素晴らしいコードを提供してくれた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
サブ終了
アプリケーションがAccessデータベースへの接続を開きすぎています。合計で2048になるSQLステートメントのテーブルだけでなく、フォーム、レポート、コンボボックス、閉じられていないレコードセットなどでさえ、アプリケーションで使用される接続の数になります。ここで試すことができるいくつかのこと:
1。実際に使用していないリソース(レコードセットなど)を閉じます。
2.ドメインアガーゲート機能(DLookupなど)を使用している場合は、Elookupを使用して変更します。これは、それ自体が明示的にクリーンアップされるためです。
3.一時テーブルを利用するようにSQLコードを変更できます。
それが役に立てば幸い。