Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

Tabellen umbenennen

Begonnen von THK, November 29, 2016, 09:59:10

⏪ vorheriges - nächstes ⏩

THK

Hallo Zusammen,
ich betreibe eine Access-DB mit per ODBC angebundenen Tabellen aus einer MySQL-DB.
Damit ich auch ohne Zugang auf die MySQL-DB weiter an der Access-DB entwickeln kann, halte ich die Tabelle auch als lokale Tabelle. Um diese schnell nutzbar zu machen benenne ich die ODBC-Tabelle einfach um (z.B. tbl_Dokumente ind tbl_Dokumente2). Die lokalen Tabellen dann ebenfalls (von tbl_Dokumente1 in tbl_Dokumente).
Das klappt mit alles Tabellen mit Ausnahme den, die im aktuellen Formular Basis für 2 Unterformulare sind. Das obwohl ich das Formular zuvor mit docmd.close geschlossen habe.

Mein Vorgehen sieht also wie folgt aus:
1. Öffnen von Formular1
2. Öffnen von Formular2 (ohne Datenbindung) über Befehlsschatfläche in Formular1
3. NachLaden von Formular 2, schließen von Formular1
4. Umbenennen der ODBC-Tabellen
5. Umbenennen der lokalen Tabellen
6. Starten des Formular1
7. Wenn Fomular2 geöffnet ist, dann Formular2 schließen.

Das funktioniert super, wenn ich von ODBC auf lokale Tabebelle wechsele.
Beim Wechsel von lokal auf ODBC-Tabelle erhalte ich allerdings die Meldung:

ZitatDas Datenbankmodul konnte die tabelle 'tbl_Dokumente' nicht sperren, da sie bereits von einem anderen Benutzer oder Vorgang bearbeitet wird.

Hat da jemand eine Lösung parat?

   

THK

Hier noch mein Code zum Umbenennen:

Public Sub WechselnVerknüpfung(Optional MitAusnahmenliste As String = "")
On Error GoTo Fehler
Dim cnn As ADODB.Connection
Dim cat As ADOX.Catalog
Dim tbl As ADOX.Table
Dim prop As Property
Dim rst As New ADODB.Recordset
Dim fld As ADODB.Field
Dim Ausnahmen() As String
b = 0
Set cnn = CurrentProject.Connection
Set cat = New ADOX.Catalog
cat.ActiveConnection = cnn
For Each tbl In cat.Tables
   If tbl.Type = "PASS-THROUGH" Then
    If Right(tbl.Name, 1) = "1" Then  'DSN-Tabellen sind inaktiv
     strInType = "DSN"
    Else
     strInType = "Lokal"
    End If
    Exit For
   End If
Next tbl
Debug.Print "Zu Type: "; strInType

If Len(MitAusnahmenliste) > 1 Then
    rst.Open MitAusnahmenliste, cnn, adOpenStatic, adLockReadOnly
    ReDim Ausnahmen(rst.RecordCount - 1)
    Debug.Print "Anzahl Ausnahmen:", rst.RecordCount
    Do While Not rst.EOF
        Ausnahmen(b) = rst(0)
        Debug.Print Ausnahmen(b) & "/";
        b = b + 1
        rst.MoveNext
    Loop
    Debug.Print
Else
Ausnahmen(0) = "@@@"
End If
rst.Close


If strInType = "DSN" Then
    For Each tbl In cat.Tables
       If tbl.Type = "Table" And Not StrInArry(Ausnahmen, tbl.Name) Then
       
        tbl.Name = tbl.Name & "2"
       End If
    Next tbl
    For Each tbl In cat.Tables
       If tbl.Type = "PASS-THROUGH" Then tbl.Name = Left(tbl.Name, Len(tbl.Name) - 1)
    Next tbl
Else
    For Each tbl In cat.Tables
       If tbl.Type = "PASS-THROUGH" Then tbl.Name = tbl.Name & "1"
    Next tbl
    For Each tbl In cat.Tables
       If tbl.Type = "Table" And Not StrInArry(Ausnahmen, tbl.Name) Then tbl.Name = Left(tbl.Name, Len(tbl.Name) - 1)
    Next tbl
End If
cat.Tables.Refresh
Set cat = Nothing
cnn.Close
Set cnn = Nothing
Debug.Print "Fertig bei " & UBound(Ausnahmen) + 1 & " Ausnahmen!"
Exit Sub
Fehler:
MsgBox Err.Description, vbCritical, Err.Number
Resume Next
End Sub


MaggieMay

Hi,

die sauberste Lösung wäre wohl, die Tabellen jeweils neu einzubinden.
Freundliche Grüße
MaggieMay

PhilS

Zitat von: MaggieMay am November 30, 2016, 05:04:24die sauberste Lösung wäre wohl, die Tabellen jeweils neu einzubinden.
+1
Außerdem solltest du dir überlegen, ob du nicht auf deinem lokalen Rechner ebenfalls MySQL installierst und dort eine Entwicklungsversion der Datenbank betreibst, deren Tabellen du als Alternative zur Produktiv-DB einbindest.

Access und MySQL verhalten sich teilweise recht unterschiedlich, daher wäre es sicherlich besser immer mit dem tatsächlichen Backend-System zu arbeiten und so Stärken von MySQL besser nutzen zu können und Probleme frühzeitig zu erkennen.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

THK

Danke für die bisherigen Tipps, Ihre habt natürlich recht.
Aber...

die Frage ist doch, wieso und wodurch ist eine Tabelle gesperrt und kann über VBA nicht umbenannt werden, wenn ich doch zuvor das Formular, welches die Tabelle als Datenbasis für ein Unterfomular hat,  über den VBA-Code des zweiten Formulars (ungebunden) geschlossen habe?

THK

Darf ich fragen, ob dieses Thema zu banal für dieses Forum ist?

MaggieMay

Das Thema ist sicherlich nicht banal, aber mAn bereits geklärt.

Wenn du meiner Empfehlung folgen würdest, könnte dies die Lösung sein. Warum also suchst du noch nach anderen bzw. willst deinen nicht funktionierenden Weg unbedingt weiterverfolgen?

Freundliche Grüße
MaggieMay

THK

Gerne!
Das Problem liegt ja nicht bei der Anbindung an die ODBC-Tabellen, sondern bei der Umbenennung der internen Tabellen und dem Zugriffs-Fehler.

Z.B.
1. Ich nutze gerade die lokalen Tabellen (tbl_Kunden);
2. die ungenutzten ODBC-Tabellen  haben derweil den gleichen Namen mit einer angehängten 2 (tbl_Kunden2).
3. Nun benenne ich zunächst die lokalen Tabellen um indem ich eine 1 anhänge (tbl_Kunden1) ,
4. dann die ODBC-Tabellen indem ich die 2 entferne.

Schritt 3 wird allerdings im Falle von 2 Tabellen (von 10) abgelehnt, das diese gerade von einem weiteren Benutzer verwendet werden.

Die beiden Tabellen waren kurz zuvor Basis für 2 Unterformulare des kurz vor der Umbenennungsaktion geschlossenen Formulars.

Wie finde ich nun raus, wo und wie die beiden Tabellen noch genutzt werden?

Übrigens, wenn ich derart von ODBC-Tabellen auf lokale Tabellen wechsele, sind die beiden ODBC-Tabellen problemlos unzubenennen. Die werden wohl nicht von dem anderen Benutzer verwendet.

PhilS

Zitat von: THK am Dezember 01, 2016, 13:54:22Darf ich fragen, ob dieses Thema zu banal für dieses Forum ist?
Die Frage ist keineswegs banal. - Sie ist nur schwer per Ferndiagnose zu beantworten.

Zitat von: THK am Dezember 02, 2016, 15:12:35
Schritt 3 wird allerdings im Falle von 2 Tabellen (von 10) abgelehnt, das diese gerade von einem weiteren Benutzer verwendet werden.

Die beiden Tabellen waren kurz zuvor Basis für 2 Unterformulare des kurz vor der Umbenennungsaktion geschlossenen Formulars.

Wie finde ich nun raus, wo und wie die beiden Tabellen noch genutzt werden?
Genau das ist der schwierige Teil. - Eigentlich sollten sie geschlossen sein, wenn keine Abfragen und Formulare mehr geöffnet sind, die diese Tabellen als Datenherkunft verwenden.
Kann es sein, dass du innerhalb der betreffenden Formulare oder anderswo im Code diese Tabellen in einem Recordset geöffnet hast, dass nicht sauber geschlossen wird?
Funktioniert das Umbenennen, wenn du die DB schließt, wieder öffnest und dann den Code zur Umbenennung laufen lässt, ohne dass vorher irgendein anderer Code gelaufen ist?
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor

MaggieMay

Was ich meine ist, dass deine Theorie bzw. Umsetzung einfach der falsche Weg ist.

Binde die Tabellen beim Start der DB wahlweise via ODBC oder alternativ als Access-
Tabellen ein.
Dazu brauchst du natürlich zwei verschiedene Backends, aber das dürfte wohl das
geringste Problem sein.
Freundliche Grüße
MaggieMay

crystal

Hallo THK,
zugegeben ist dein Unterfangen etwas ungewöhnlich.

Ich hatte vor Jahren ein ähnliches Problem (Hin- und Herschalten zwischen Test- und Produktions-DB) und mein Ansatz war, alle SQL-Statements (Abfragen) zur Laufzeit von einem Modul übersetzen zu lassen.

Dazu muss man natürlich eiges tun, z. B. im Load-Event eines Formulars alle SQL-Quellen (Form selbst, Subforms, Komboboxen usw.) übersetzen.

Inzwischen kenne ich die Tempvars. Vielleicht wäre es möglich, mit ihnen beim Start der Anwendung und Prüfung online/offline zu arbeiten.
Nach dem Schema:
Beim Start der Anwendung für jede Tabelle genau eine Tempvar anlegen und in Abhängigkeit von Online/Offline den passenden Tabellen-Namen zuweisen, z.B.
' Tempvar-Name ist "TV_TabSample"
if online then
  Tempvars.Add "TV_TabSample", "Tab_Sample1"
else
  Tempvars.Add "TV_TabSample", "Tab_Sample2"
endif

Somit hättest du EINEN neuen Namen, den du in Selects benutzen könntest, z.B.
select <irgendwas> from TV_TabSample ...
statt
select <irgendwas> from Tab_Sample1 ...

Du müsstest nur sicherstellen, dass dein Definitions-Modul aufgerufen wird. Die Tempvars bleiben dann solange erhalten, bis Access beendet oder ein neuer Wert zugewiesen wird.

Ich habe das hier jetzt nicht getestet, aber vielleicht wäre es ein Ansatz. Bitte suche selbst einmal nach Tempvars in Access.

Übrigens könnten die Umbenennungs-Fehler auch darauf zurückzuführen sein, dass du Verknüpfungen zwischen Tabellen hast. Dann müsste man zuerst die Verknüpfung löschen, dann die Tabellen umbenennen und die Verküpung neu erstellen.

Ich würde auch davon abraten, Tabellen jedesmal umzubenennen, weil das nur ohne zuvoriges Löschen von Verküpfungen ginge und es eigentlich keine DB ohne Verküfpungen gibt...

Noch eine Idee: du könntest versuchen, eine dreistufige Hierarchie aufzubauen:
1. deine Access-DB (als Frontend, nur Code, keine eigenen Tabellen)
2. zwei unterschiedliche Access-"Backends" als "Zwischen-DB", eine mit eingebundenen ODBC-Tabellen, eine mit eingebundenen Access-Tabellen (also zwei Access-DBs, in denen nur eingebundene Tabellen, aber kein Code vorhanden ist, allenfalls Abfragen)
3. die ODBC-DB bzw. eine Access-DB mit Daten

Dann müsstest du nur die "Zwischen-DB" umbenennen und zwar auf EINEN definierten Namen, den du in deinem Frontend einbindest.

Dies sind nur Gedanken, bitte prüfe deren Machbarkeit und warte darauf, was andere dazu vielleicht zu sagen haben.

lg
crystal

Wer Fehler in meinen Antworten findet, darf sie behalten, muss sie aber kommentieren. ;-)
Dies ist keineswegs arrogant gemeint, sondern soll nur unterstreichen, dass meine Antworten - natürlich - nicht immer fehlerfrei sind und sein können.
Devise: bitte immer erst selbst probieren!

Aus gesundheitlichen Gründen nur noch selten dabei...

PhilS

Zitat von: crystal am Dezember 04, 2016, 16:09:37' Tempvar-Name ist "TV_TabSample"
if online then
  Tempvars.Add "TV_TabSample", "Tab_Sample1"
else
  Tempvars.Add "TV_TabSample", "Tab_Sample2"
endif

Somit hättest du EINEN neuen Namen, den du in Selects benutzen könntest, z.B.
select <irgendwas> from TV_TabSample ...
Direkt einen Ausdruck oder eine TempVar als Tabelle/Abfrage innerhalb eine FROM-Klausel zu verwenden funktioniert leider nicht.
Um diesen Ansatz zu nutzen müsste man per VBA die SQL-Statements alles Abfragen entsprechend ändern und das geänderte SQL speichert. - Davon würde ich abraten.
Neue Videoserie: Windows API in VBA

Klassische CommandBars visuell bearbeiten: Access DevTools CommandBar Editor