Błąd "Baza danych jest w nieoczekiwanym stanie" po otwarciu bazy danych w programie Access

W tym artykule rozwiązaje problem występujący podczas konwertowania bazy danych za pomocą biblioteki DAO.

Uwaga

Nazwa usługi Office 365 ProPlus została zmieniona na Aplikacje usługi Microsoft 365 dla przedsiębiorstw. Aby uzyskać więcej informacji na temat tej zmiany, przeczytaj ten wpis w blogu.

Oryginalny numer KB:   888634

Uwaga

Ten artykuł dotyczy pliku bazy danych programu Microsoft Access (mdb) lub pliku bazy danych programu Microsoft Access (accdb). Wymaga podstawowych umiejętności makro, kodowania i interoperacyjności.

Symptomy

Podczas próby otwarcia bazy danych w programie Microsoft Access 2000 lub nowszej wersji zostanie wyświetlony następujący komunikat o błędzie:

Baza danych jest w nieoczekiwanym stanie

Przyczyna

Ten problem może wystąpić podczas korzystania z biblioteki obiektu dostępu do danych (DAO) do konwertowania bazy danych utworzonej w programie Microsoft Access 97 lub starszej wersji przy użyciu CompactDatabase tej metody. CompactDatabaseMetoda może pozostawić nową bazę danych w stanie częściowo przekonwertowane.

Rozwiązanie

Aby rozwiązać ten problem, należy użyć jednej z następujących metod.

Metoda 1: Użyj polecenia Konwertuj bazę danych, gdy masz oryginalną bazę danych

Jeśli nadal masz kopię oryginalnej bazy danych w oryginalnym formacie, użyj Convert Database polecenia. Aby to zrobić, wykonaj następujące kroki.

Program Access 2000, Access 2002 lub Access 2003

  1. Utwórz kopię zapasową oryginalnej bazy danych.

  2. Uruchom program Access 2000 lub nowszą wersję.

  3. W menu Narzędzia kliknij polecenie Narzędzia bazy danych, kliknij polecenie Konwertuj bazę danych, a następnie kliknij polecenie Aby uzyskać dostęp do formatu pliku 2000.

    Uwaga

    Jeśli używasz programu Access 2000, w menu Konwertuj bazę danych pojawi się tylko do bieżącej wersji bazy danych dostępu.

  4. W oknie dialogowym Baza danych do konwersji z kliknij nazwę pliku bazy danych, który chcesz przekonwertować, a następnie kliknij pozycję Konwertuj.

  5. W oknie dialogowym Konwertowanie bazy danych na wpisz nową nazwę pliku bazy danych, a następnie kliknij przycisk Zapisz.

Dostęp 2007

  1. Utwórz kopię zapasową oryginalnej bazy danych.
  2. Spróbuj otworzyć tę bazę danych.
  3. Po otwarciu bazy danych mdb w formacie programu Access 97 lub Access 95 program Access wyświetli okno dialogowe Ulepszenie bazy danych. Zostanie wyświetlony monit o uaktualnienie bazy danych.
  4. Kliknij przycisk Tak, aby uaktualnić bazę danych do dowolnego formatu pliku wybranego jako domyślny format pliku w programie Access 2007. Po przekonwertowaniu bazy danych można wprowadzić zmiany w projekcie pliku w programie Access 2007. Jednak nie można już otworzyć bazy danych przy użyciu wersji programu Access wcześniej niż wersja, na którą przekonwertowano bazę danych.

Metoda 2: Odzyskiwanie danych bazy danych i zapytań bazy danych, gdy nie masz oryginalnej niezabezpieczonej bazy danych

Jeśli nie masz kopii oryginalnej niezabezpieczonej bazy danych w oryginalnym formacie i wypróbowano standardowe techniki rozwiązywania problemów z uszkodzeniem, spróbuj odzyskać dane bazy danych i kwerendy bazy danych. Aby to zrobić, wykonaj następujące kroki.

  1. Utwórz kopię zapasową oryginalnej bazy danych.

  2. Uruchom program Access 2000 lub nowszą wersję.

  3. Program Access 2000, Access 2002 lub Access 2003

    • Kliknij pozycję Pusta baza danych programu Access, wpisz nową nazwę bazy danych w polu Nazwa pliku, a następnie kliknij przycisk Utwórz.

    Dostęp 2007

    • Kliknij przycisk Office, kliknij pozycję Nowy, kliknij pozycję Pusta baza danych, a następnie kliknij pozycję Utwórz, aby utworzyć nową pustą bazę danych.
  4. Program Access 2000, Access 2002 lub Access 2003

    • W menu Wstaw kliknij polecenie Moduł. Zostanie uruchomiony edytor Microsoft Visual Basic Editor i zostanie utworzony nowy moduł.

    Dostęp 2007

    • Na karcie Tworzenie kliknij strzałkę w dół poniżej makra, a następnie kliknij pozycję Moduł. Zostanie uruchomiony edytor Microsoft Visual Basic Editor i zostanie utworzony nowy moduł.
  5. W menu Narzędzia kliknij polecenie Odwołania.

  6. Na liście Dostępne odwołania znajdź bibliotekę obiektów Dao 3.6 firmy Microsoft, a następnie kliknij, aby zaznaczyć pole wyboru Biblioteka obiektów Microsoft DAO 3.6.

    Uwaga

    DAO 3.6 jest również dostępny w systemie Windows XP Home Edition.

  7. Aby zamknąć okno dialogowe Odwołania, kliknij przycisk OK.

  8. Wklej następujący kod do nowego utworzonego modułu.

    Sub RecoverCorruptDB()
     Dim dbCorrupt As DAO.Database
     Dim dbCurrent As DAO.Database
     Dim td As DAO.TableDef
     Dim tdNew As DAO.TableDef
     Dim fld As DAO.Field
     Dim fldNew As DAO.Field
     Dim ind As DAO.Index
     Dim indNew As DAO.Index
     Dim qd As DAO.QueryDef
     Dim qdNew As DAO.QueryDef
     Dim strDBPath As String
     Dim strQry As String
    
     ' Replace the following path with the path of the
     ' corrupted database.
     strDBPath = "C:\My Documents\yourDatabase.mdb"
    
     On Error Resume Next
     Set dbCurrent = CurrentDb
     Set dbCorrupt = OpenDatabase(strDBPath)
    
     For Each td In dbCorrupt.TableDefs
         If Left(td.Name, 4) <> "MSys" Then
             strQry = "SELECT * INTO [" & td.Name & "] FROM [" & td.Name & "] IN '" & dbCorrupt.Name & "'"
             dbCurrent.Execute strQry, dbFailOnError
             dbCurrent.TableDefs.Refresh
             Set tdNew = dbCurrent.TableDefs(td.Name)
    
     ' Re-create the indexes on the table.
             For Each ind In td.Indexes
                 Set indNew = tdNew.CreateIndex(ind.Name)
                 For Each fld In ind.Fields
                     Set fldNew = indNew.CreateField(fld.Name)
                     indNew.Fields.Append fldNew
                 Next
                 indNew.Primary = ind.Primary
                 indNew.Unique = ind.Unique
                 indNew.IgnoreNulls = ind.IgnoreNulls
                 tdNew.Indexes.Append indNew
                 tdNew.Indexes.Refresh
             Next
         End If
     Next
    
     ' Re-create the queries.
     For Each qd In dbCorrupt.QueryDefs
         If Left(qd.Name, 4) <> "~sq_" Then
             Set qdNew = dbCurrent.CreateQueryDef(qd.Name, qd.SQL)
         End If
     Next
    
     dbCorrupt.Close
     Application.RefreshDatabaseWindow
     MsgBox "Procedure Complete."
    End Sub
    

    Uwaga

    Kod spróbuje zaimportować wszystkie tabele i wszystkie kwerendy z uszkodzonej bazy danych do bieżącej bazy danych. C:\My Documents\yourDatabase.mdbZastąp poprawną ścieżką i nazwą pliku bazy danych.

  9. Aby uruchomić kod, w menu Uruchom kliknij polecenie Uruchom formularz podrzędny/użytkownika.

Metoda 3: Odzyskiwanie danych bazy danych, gdy nie masz oryginalnej zabezpieczonej bazy danych

Jeśli nie masz kopii oryginalnej zabezpieczonej bazy danych w oryginalnym formacie i wypróbowano standardowe techniki rozwiązywania problemów z uszkodzeniem, spróbuj odzyskać dane bazy danych. Aby to zrobić, wykonaj następujące kroki.

  1. Utwórz kopię zapasową oryginalnej bazy danych.

  2. Uruchom program Access 2000 lub nowszą wersję.

  3. Program Access 2000, Access 2002 lub Access 2003

    • Kliknij pozycję Pusta baza danych programu Access, wpisz nową nazwę bazy danych w polu Nazwa pliku, a następnie kliknij przycisk Utwórz.

    Dostęp 2007

    • Kliknij przycisk pakietu Microsoft Office, kliknij pozycję Nowy, kliknij pozycję Pusta baza danych, a następnie kliknij pozycję Utwórz, aby utworzyć nową pustą bazę danych.
  4. Program Access 2000, Access 2002 lub Access 2003

    • W menu Wstaw kliknij polecenie Moduł. Zostanie uruchomiony edytor Microsoft Visual Basic Editor i zostanie utworzony nowy moduł.

    Dostęp 2007

    • Na karcie Tworzenie kliknij strzałkę w dół poniżej makra, a następnie kliknij pozycję Moduł. Zostanie uruchomiony edytor Microsoft Visual Basic Editor i zostanie utworzony nowy moduł.
  5. W menu Narzędzia kliknij polecenie Odwołania.

  6. Na liście Dostępne odwołania znajdź bibliotekę obiektów Dao 3.6 firmy Microsoft, a następnie kliknij, aby zaznaczyć pole wyboru Biblioteka obiektów Microsoft DAO 3.6.

  7. Aby zamknąć okno dialogowe Odwołania, kliknij przycisk OK.

  8. Wklej następujący kod do nowego utworzonego modułu.

    Option Compare Database
    
    Function BackupSecureDatabase()
    
     On Error GoTo Err_BackupSecureDatabase
     Dim wrkDefault As DAO.Workspace
     Dim dbsNew As DAO.Database
     Dim dbeSecure As DAO.PrivDBEngine
     Dim wrkSecure As DAO.Workspace
     Dim dbsSecure As DAO.Database
     Dim tdfSecure As DAO.TableDef
     Dim strSecureUser As String
     Dim strSecurePwd As String
     Dim strSecurePathToDatabase As String
     Dim strSecurePathToWorkgroupFile As String
     Dim strTableName As String
     Dim strSQL As String
     Dim dbsTemp As DAO.Database
     Dim strTempPathToDatabase As String
     Dim strBackupPathToDatabase As String
     Dim strLogPath As String
     Dim SourceRec As DAO.Recordset
     Dim DestRec As DAO.Recordset
    
     ' Set the variables (change for environment).
     strSecurePathToDatabase = "C:\MyDatabases\Northwind.mdb"
     strSecurePathToWorkgroupFile = "C:\MyDatabases\Secured.mdw"
     strSecureUser = "Administrator"
     strSecurePwd = "password"
     strTempPathToDatabase = "C:\MyDatabases\Temp.mdb"
     strBackupPathToDatabase = "C:\MyDatabases\Backup.mdb"
     strLogPath = "C:\MyDatabases\Backup.log"
    
     ' Open the log file.
     Open strLogPath For Output As #1
     Print #1, Time, "Log file opened"
     Print #1, Time, "Variables set"
    
     ' Delete old files.
     If Dir(strTempPathToDatabase) <> "" Then Kill strTempPathToDatabase
     If Dir(strBackupPathToDatabase) <> "" Then Kill strBackupPathToDatabase
     Print #1, Time, "Old backup files deleted"
    
     ' Create the new temp database.
     Set wrkDefault = DBEngine.Workspaces(0)
     Set dbsNew = wrkDefault.CreateDatabase(strTempPathToDatabase, dbLangGeneral)
     Set dbsNew = Nothing
     Print #1, Time, "Temp database created"
    
     ' Open the secured database.
     Set dbeSecure = New PrivDBEngine
     dbeSecure.SystemDB = strSecurePathToWorkgroupFile
     dbeSecure.DefaultUser = strSecureUser
     dbeSecure.DefaultPassword = strSecurePwd
    
     Set wrkSecure = dbeSecure.Workspaces(0)
     Set dbsSecure = wrkSecure.OpenDatabase(strSecurePathToDatabase)
     Print #1, Time, "Secured database opened from " & strSecurePathToDatabase
    
     ' Open the temp database.
     DBEngine(0).CreateUser
     Set dbsTemp = DBEngine(0).OpenDatabase(strTempPathToDatabase)
    
     Print #1, Time, "Temp database opened from " & strTempPathToDatabase
    
     ' Loop through the tables in the secured database.
     For Each tdfSecure In dbsSecure.TableDefs
        strTableName = tdfSecure.Name
        If Left(strTableName, 4) <> "MSys" Then
            Print #1, Time, "Export of " & strTableName
            ' Copy the table definition to the temp database.
            If CopyTableDef(tdfSecure, dbsTemp, strTableName) Then
                ' Then append all the data into the table.
                 Set SourceRec = tdfSecure.OpenRecordset(dbOpenTable, dbReadOnly)
                 Set DestRec = dbsTemp.OpenRecordset(strTableName)
                 AppendRecordsFromOneRecordSetToAnother SourceRec, DestRec 
                 SourceRec.Close
                 DestRec.Close
    
            End If
        End If
     Next tdfSecure
    
     ' Close open objects.
     dbsSecure.Close
     Print #1, Time, "Secured database closed"
     dbsTemp.Close
     Print #1, Time, "Temp database closed"
    
     ' Compact the database into the backup database.
     DBEngine.CompactDatabase strTempPathToDatabase, strBackupPathToDatabase, dbLangGeneral
     Print #1, Time, "New backup database created at " & strBackupPathToDatabase
    
     ' Delete the temp database.
     If Dir(strTempPathToDatabase) <> "" Then Kill strTempPathToDatabase
     Print #1, Time, "Temp database deleted"
     Print #1, Time, "Log file closed"
     Close #1
    
    Exit_BackupSecureDatabase:
    
     Set wrkDefault = Nothing
     Set dbsNew = Nothing
     Set dbeSecure = Nothing
     Set wrkSecure = Nothing
     Set dbsSecure = Nothing
     Set tdfSecure = Nothing
     Set dbsTemp = Nothing
     Exit Function
    
    Err_BackupSecureDatabase:
       Print #1, Time, "     ***ERROR: " & Err.Number, Err.Description, strTableName
       Resume Next
    
    End Function
    
    Function CopyTableDef(SourceTableDef As TableDef, TargetDB As Database, TargetName As String) As Integer
    Dim SI As DAO.Index, SF As DAO.Field, SP As DAO.Property
    Dim T As DAO.TableDef, I As DAO.Index, F As DAO.Field, P As DAO.Property
    Dim I1 As Integer, f1 As Integer, P1 As Integer
    
     If SourceTableDef.Attributes And dbAttachedODBC Or SourceTableDef.Attributes And dbAttachedTable Then
      CopyTableDef = False
      Exit Function
     End If
     Set T = TargetDB.CreateTableDef(TargetName)
    
     ' Copy Jet Properties.
      On Error Resume Next
      For P1 = 0 To T.Properties.Count - 1
       If T.Properties(P1).Name <> "Name" Then
         T.Properties(P1).Value = SourceTableDef.Properties(P1).Value
       End If
      Next P1
     On Error GoTo 0
    
     ' Copy Fields.
       For f1 = 0 To SourceTableDef.Fields.Count - 1
        Set SF = SourceTableDef.Fields(f1)
    
        ' DAO 3.0 and later versions. ****
        If (SF.Attributes And dbSystemField) = 0 Then
         Set F = T.CreateField()
         ' Copy Jet Properties.
           On Error Resume Next
           For P1 = 0 To F.Properties.Count - 1
             F.Properties(P1).Value = SF.Properties(P1).Value
           Next P1
           On Error GoTo 0
         T.Fields.Append F
        End If ' Corresponding End If ****
     Next f1
    
    ' Copy Indexes.
     For I1 = 0 To SourceTableDef.Indexes.Count - 1
       Set SI = SourceTableDef.Indexes(I1)
    
    ' Foreign indexes are added by relationships.
       If Not SI.Foreign Then
         Set I = T.CreateIndex()
         ' Copy Jet Properties.
           On Error Resume Next
           For P1 = 0 To I.Properties.Count - 1
             I.Properties(P1).Value = SI.Properties(P1).Value
           Next P1
           On Error GoTo 0
         ' Copy Fields.
           For f1 = 0 To SI.Fields.Count - 1
             Set F = T.CreateField(SI.Fields(f1).Name, T.Fields(SI.Fields(f1).Name).Type)
             I.Fields.Append F
           Next f1
         T.Indexes.Append I
       End If
     Next I1
    
    ' Append TableDef.
     TargetDB.TableDefs.Append T
    
    ' Copy Access/User Table Properties.
     For P1 = T.Properties.Count To SourceTableDef.Properties.Count - 1
       Set SP = SourceTableDef.Properties(P1)
       Set P = T.CreateProperty(SP.Name, SP.Type)
       P.Value = SP.Value
       T.Properties.Append P
     Next P1
    
    ' Copy Access/User Field Properties.
     For f1 = 0 To T.Fields.Count - 1
       Set SF = SourceTableDef.Fields(f1)
       Set F = T.Fields(f1)
       For P1 = F.Properties.Count To SF.Properties.Count - 1
         Set SP = SF.Properties(P1)
         Set P = F.CreateProperty(SP.Name, SP.Type)
         P.Value = SP.Value
         F.Properties.Append P
       Next P1
     Next f1
    
    ' Copy Access/User Index Properties.
     For I1 = 0 To T.Indexes.Count - 1
       Set SI = SourceTableDef.Indexes(T.Indexes(I1).Name)
    
    ' Do not copy foreign indexes. They are created by relationships.
       If Not SI.Foreign Then
         Set I = T.Indexes(I1)
         For P1 = I.Properties.Count To SI.Properties.Count - 1
           Set SP = SI.Properties(P1)
           Set P = I.CreateProperty(SP.Name, SP.Type)
           P.Value = SP.Value
           I.Properties.Append P
         Next P1
       End If
      Next I1
     CopyTableDef = True
    End Function
    
    Function AppendRecordsFromOneRecordSetToAnother(SR As DAO.Recordset, DR As DAO.Recordset)
    Dim x As Integer
    
    Do While Not SR.EOF
    DR.AddNew
     For x = 0 To SR.Fields.Count - 1
         DR(x).Value = SR(x).Value
     Next x
    DR.Update
    SR.MoveNext
    Loop
    End Function
    

    Uwaga

    Kod spróbuje zaimportować wszystkie tabele z uszkodzonej bazy danych do zapasowej bazy danych. Zastąp zmienne w tabeli po kroku 10 lokalizacjami plików bazy danych i ustawieniami użytkownika.

  9. Na liście funkcji wybierz pozycję BackupSecureDatabase.

  10. Aby uruchomić kod, w menu Uruchom kliknij polecenie Uruchom formularz podrzędny/użytkownika.

    Zmiennej Opis
    strSecurePathToDatabase Lokalizacja zabezpieczonego pliku bazy danych
    strSecurePathToWorkgroupFile Lokalizacja pliku grupy roboczej
    strSecureUser Zabezpieczona nazwa logowania użytkownika
    strSecurePwd Zabezpieczone hasło logowania użytkownika
    strTempPathToDatabase Lokalizacja tymczasowego pliku bazy danych
    strBackupPathToDatabase Lokalizacja pliku kopii zapasowej bazy danych
    strLogPath Lokalizacja pliku dziennika

Stan

Firma Microsoft potwierdziła, że jest to problem w produktach firmy Microsoft wymienionych w sekcji "Dotyczy".

Więcej informacji

Aby uzyskać więcej informacji dotyczących rozwiązywania problemów z uszkodzeniem w bazie danych programu Microsoft Access, zobacz następujący artykuł:

Kompaktowanie i naprawianie bazy danych