2012-09-25 7 views
8

Mentre alle prese con una sola eredità MS applicazione di Access Ho affrontato questo errore strano:MS Access 2010: "Impossibile aprire altri database".

Cannot open any more databases. 

L'applicazione fa ampio uso di UNION istruzioni SQL. Quindi questo sembra causare l'accesso al limite di 2048 tabelle aperte. Qualche altra possibilità che sbarazzarsi di questi sindacati?

+3

Wow, 2048 tavoli .. per interesse come ha fatto le cose si fanno così male? –

+0

Naturalmente non ci sono molte tabelle nel DB. Ci sono meno di 50 tabelle e circa 100 query. – Christian

+0

Nonostante il clou di Kieren, sono stupito che nessuna delle risposte fornite sia più incline a un serio ripensamento dell'UNION sql, se la struttura dei dati è ottimizzata bene, allora non dovresti mai avere bisogno di finire con una query così grande. Particolarmente brutto in accesso in quanto viene eseguito localmente e potrebbe richiedere una vita intera. –

risposta

4

Ho riscontrato questo problema durante l'utilizzo di tabelle esterne collegate. Il limite è stato raggiunto perché circa 10 file excel sono stati utilizzati più volte da diverse query. Quindi il numero di tavoli aperti era più o meno il prodotto di query e tabelle.

Immagino che usare i sindacati moltiplica anche questo problema.

La soluzione per me era copiare le tabelle excel collegate in tabelle nativi di Access. Quindi esegui le stesse query con le tabelle native.

+0

Il messaggio tedesco è "Fehler 3048: Mehr Datenbanken können nicht geöffnet werden' btw. – msjav

+0

Wow, e ottiene le grandezze più velocemente da modificare ed esegue le query in questo modo. È un po 'schifoso che Access non lo gestisca da solo. Ma per il mio caso questa soluzione è ok. – Christian

1

L'unico vero problema è utilizzare un insieme temporaneo di tabelle. Inserisci i risultati dei tuoi sindacati in tabelle temporanee e usali per limitare il numero di tabelle per query. Di solito prefisso le mie tabelle temporanee con un trattino basso (_tmpCustomers) e poi li distruggono quando ho finito.

+0

Uh, non ho capito prima questa risposta. Immagino che tu intendessi lo stesso come msjav? – Christian

+0

Sì, ma la mia risposta non era molto chiara ... avrei dovuto usare degli esempi davvero, includerò degli esempi in futuro per aiutare :) – twoleggedhorse

0

L'applicazione sta tentando di aprire troppe connessioni al database di Access. Non solo le tabelle nella tua istruzione sql che si sommano al 2048, anche i moduli, i report, le caselle combinate, i recordset non chiusi ecc. Si sommano al numero di connessioni utilizzate dall'applicazione. Poche cose che puoi provare qui:
1. Chiudi le risorse (es. Set di record) che non stai realmente utilizzando.
2. Se si utilizzano le funzioni di aggancio del dominio (ad es. DLookup), cambiarlo con Elookup mentre si ripulisce esplicitamente da solo.
3. È possibile modificare il codice SQL per utilizzare Temp Tables.
Spero che aiuti.

+0

Chiudere le risorse non aiuterà, immagino. Posso avviare l'applicazione, eseguire una query (senza vba) e l'errore si verifica. Come possono aiutare i tavoli temporanei qui? Puoi fare un esempio? – Christian

2

Spesso, questo si verifica con moduli grandi/complessi con molte sottomaschere e/o caselle combinate/caselle di riepilogo.

Prova a fare ciò che Saurabh dice. Sono comunque buone cose. Ma penso che questi cambiamenti non risolveranno il tuo problema.

Recentemente, ho risolto lo stesso problema. Ho identificato che si verifica sempre quando un determinato modulo è stato aperto. Questa forma aveva molte sottomaschere e combo.

Primo. Cerca di semplificare la forma o le forme: hai davvero bisogno di tutte le sottomaschere? Tutte le sottomaschere devono essere caricate sempre?

Ho risolto il problema con la distribuzione di sottomaschere in diverse pagine di un controllo struttura a schede. Quindi caricare e scaricare le sottomaschere in modo dinamico in Modifica evento.

Inizialmente, solo le sottomaschere sulla prima pagina devono avere la proprietà "SourceObject" assegnata. Il resto, ha questa proprietà vuota.

Nel caso in cambiamento, provare a fare qualcosa di simile:

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 

Questa è una funzione generica per iterare su tutti i controlli subform. Se non è nella pagina attiva, scaricarlo. In altri casi, prendi l'oggetto sorgente dalla proprietà del tag.

Dovrai evitare riferimenti a sottomoduli scaricati, cioè, se "Subform1" viene scaricato si otterrà un errore con qualcosa di simile: Me.Subform1.Form.InvoiceId

Questo cambiamento hanno altri benefici. Il tuo modulo verrà caricato più velocemente e la navigazione nella registrazione sarà più veloce.

+0

Non ci sono forme o codice vba coinvolti, in realtà. Aprire la query accdb e execution one (specifica) è sufficiente per far apparire il messaggio di errore. Se metto i risultati delle query dipendenti in una tabella e li uso da una versione di query modificata, funziona. – Christian

+0

La tua query può chiamare funzioni aggregate o VBA. Puoi pubblicare lo sql di questa query? Lei cita una query specifica. Solo con questa query? Anche con altre domande? – ricardohzsz

+0

Il codice della query è come SELECT * FROM UNION ALL SELECT * FROM B ... - ma la risposta di msjav ha risolto molto bene il problema. – Christian

1

Voglio ringraziare ricardohzsz per il suo codice meraviglioso! Mi ha davvero aiutato a migliorare le prestazioni del mio database e ad eliminare l'errore 3048.

Vorrei votare il post ma non ho abbastanza reputazione qui per votare.

Ho dovuto apportare alcune modifiche per farlo funzionare per i miei bisogni (avevo bisogno delle sottomaschere per consentire aggiunte e modifiche e l'utilizzo di questo codice li rendeva di sola lettura). Vi metto le alterazioni qui nel caso in cui essa può aiutare qualcun altro, anche:

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