Vorbereitung
Vorbereitung zum Strukturupdate
Bevor Sie die Datenbank anpacken und updaten, sollten Sie sicher sein, dass nur ein Anwender, nämlich der, der das Update gerade aufruft, auf die Datenbank bzw. das Backend zugreift. Arbeiten mehrere Anwender mit der Datenbank kann entweder diese nicht modifiziert werden oder es kann zu Fehlern kommen. Für jede Datenbank legt die Jet-Engine, sobald die Datei (MDB/MDE) in Benutzung ist, eine LDB-Datei an. Die Datei trägt den gleichen Dateinamen wie die Datenbank. Anstatt der Endung MDB bzw. MDE ist hier das Präfix LDB. In dieser Datei speichert die Jet-Engine alle Benutzer und Hostnamen, die auf die Datenbank zugreifen. Mit den folgenden Codezeilen kann ermittelt werden, wie viele Anwender auf eine Datenbank zugreifen. Möchten Sie eine Strukturänderung durchführen, sollten Sie sicher sein, dass nicht mehr als ein Anwender auf diese Datenbank zugreift.
Zunächst wird ein neuer Datentyp angelegt. In diesen werden später die Informationen, die aus der LDB-Datei ausgelesen werden, abgelegt.
Private Type mtypLdbUserInfo Computername As String * 32 UserName As String * 32 End Type
Die Funktion CheckUserCount liefert die Zahl der Anwender dieser Datenbank zurück, die sich in ihr befinden oder befanden. Es spielt dabei keine Rolle, ob der Anwender die Datenbank direkt geöffnet hat oder über „verknüpfte Tabellen“ darauf zugreift. Liefert die Funktion einen größeren Wert als 1 zurück, sollte kein Update erfolgen.
Hinweis: Wenn ein User aus der DB rausgeht, so wird der entsprechende Eintrag in der LDB nicht gelöscht! Für den sicheren Vollzug der DB-Strukturänderungen reicht es unter Umständen, nur die Existenz der LDB abzufragen. Wenn sie nicht existiert, kann’s gemacht werden, wenn doch, dann nicht. (Auch wenn kein User in der DB ist, die LDB aber trotzdem existiert, z.B., weil Access abstürzte, sollten die Strukturänderungen nicht ablaufen, weil das ein Hinweis darauf sein könnte, dass die DB beschädigt ist oder zumindest erst mit CompactRepair behandelt werden sollte.)
Public Function CheckUserCount(ByVal psDBName As String) As Long Dim F As Integer Dim lNUsers As Long Dim lI As Long Dim UserInfo As mtypLdbUserInfo If LCase(Right(psDBName, 4)) = ".mdb" Then psDBName = Left(psDBName, Len(psDBName) - 4) + ".ldb" End If If CheckFile(psDBName) Then F = FreeFile Open psDBName For Random Shared As #F Len = Len(UserInfo) lNUsers = Int(LOF(F) / Len(UserInfo)) Close #F End If CheckUserCount = lNUsers End Function
In der Funktion CheckUserCount wird eine weitere Funktion CheckFile aufgerufen. Sie können diese Prüfung zwar beiseite lassen, aber es empfiehlt sich immer, alle Fehlerquellen abzuprüfen. Es kann sein, dass die Datenbank von einer CD exklusiv und schreibgeschützt geöffnet wurde. In diesem Fall wird keine LDB-Datei im Datenbankverzeichnis angelegt. Ohne Prüfung auf die existierende Datei würde ein Programm- bzw. Anwenderfehler auftreten.
Wenn man eine externe Datenbank modifiziert, sollte man auch prüfen, ob diese Datei existiert. Diese Prüfung kann man ebenfalls mit der Funktion CheckFile vornehmen.
Nachfolgend die Funktion zum Prüfen auf eine existierende Datei. Als Ergebnis wird True geliefert, wenn die Datei vorhanden ist. Wir die Datei nicht gefunden ist das Ergebnis False.
1. Möglichkeit über VBA
Public Function CheckFile(ByVal psFileName As String) As Boolean CheckFile = (Len(VBA.Dir(psFileName)) > 0) End Function
2. Möglichkeit über API
Beispiel:
' Deklarationen und Typen Const mclAXPATH As Long = 260 Type gtypFILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Type gtypWIN32_FIND_DATA dwFileAttributes As Long ftCreationTime As gtypFILETIME ftLastAccessTime As gtypFILETIME ftLastWriteTime As gtypFILETIME nFileSizeHigh As Long nFileSizeLow As Long dwReserved0 As Long dwReserved1 As Long cFileName As String * mclAXPATH cAlternate As String * 14 End Type Declare Function FindFirstFile Lib "kernel32" Alias _ "FindFirstFileA" _ (ByVal lpFileName As String, _ lpFindFileData As gtypWIN32_FIND_DATA) _ As Long Declare Function FindClose Lib "kernel32" _ (ByVal hFindFile As Long) _ As Long Public Function APIFileExists(ByVal psSource As String) As Boolean Const clINVALID_HANDLE_VALUE As Long = -1 Dim WFD As gtypWIN32_FIND_DATA Dim lFile As Long lFile = FindFirstFile(psSource, WFD) '// Prüfung auf gültigen Datei-Handle APIFileExists = lFile <> clINVALID_HANDLE_VALUE Call FindClose(lFile) End Function
Existiert eine Tabelle
Zum Prüfen, ob eine Tabelle bereits existiert gehen Sie wie folgt vor:
1. Variante DAO
Public Function TableExistsDAO(pDb As DAO.Database, _ ByVal psName As String) _ As Boolean Dim s As String On Error Resume Next s = pDb.TableDefs(psName).Name TableExistsDAO = (Err.Number = 0) End Function
2. Variante ADOX
Public Function TableExistsADOX(pcnn As ADODB.Connection, _ ByVal psName As String) _ As Boolean Dim s As String Dim cat As New ADOX.Catalog On Error Resume Next cat.ActiveConnection = pcnn s = cat.Tables(psName).Name TableExistsADOX = (Err.Number = 0) If Not cat Is Nothing Then Set cat = Nothing End Function