Felet "Databasen är i ett oväntat tillstånd" visas när du öppnar en databas i Access
Den här artikeln åtgärdar ett problem som uppstår när du använder DAO-biblioteket för att konvertera en databas.
Anteckning
Office 365 ProPlus byter namn till Microsoft 365-appar för företag. Mer information om den här ändringen finns i det här blogginlägget.
Ursprungligt KB-nummer: 888634
Anteckning
Den här artikeln gäller en Microsoft Access-databasfil (.mdb) eller en Microsoft Access-databasfil (.accdb). Kräver grundläggande makron, kodning och kompatibilitetsfärdigheter.
Symptom
När du försöker öppna en databas i Microsoft Access 2000 eller en senare version får du följande felmeddelande:
Databasen är i ett oväntat tillstånd
Orsak
Det här problemet kan uppstå när du använder DAO-biblioteket (Data Access Object) för att konvertera en databas som du skapade i Microsoft Access 97 eller en tidigare version med CompactDatabase metoden. Metoden CompactDatabase kan lämna den nya databasen i ett delvis konverterat tillstånd.
Lösning
Lös problemet genom att använda någon av följande metoder.
Metod 1: Använd kommandot Konvertera databas när du har den ursprungliga databasen
Om du fortfarande har en kopia av den ursprungliga databasen i dess ursprungliga format använder du Convert Database kommandot. Gör så här:
Access 2000, Access 2002 eller Access 2003
Gör en säkerhetskopia av den ursprungliga databasen.
Starta Access 2000 eller en senare version.
På Verktyg-menyn klickar du på Databasverktyg, på Konvertera databas och sedan på Till Access 2000-filformat.
Anteckning
Om du använder Access 2000 visas endast Till aktuell access-databasversion på menyn Konvertera databas.
Klicka på namnet på databasfilen som du vill konvertera i dialogrutan Databas som ska konverteras och klicka sedan på Konvertera.
Skriv det nya namnet på databasfilen i dialogrutan Konvertera databas till och klicka sedan på Spara.
Access 2007
- Gör en säkerhetskopia av den ursprungliga databasen.
- Försök öppna databasen.
- När du öppnar en Access 97- eller Access 95-filformatsdatabas visas dialogrutan Förbättring av databasen i Access. Du uppmanas att uppgradera databasen.
- Klicka på Ja om du vill uppgradera databasen till det filformat som du har valt som standardfilformat i Access 2007. När du har konverterat databasen kan du göra designändringar av filen i Access 2007. Du kan dock inte längre öppna databasen med hjälp av en tidigare version av Access än den version som du konverterade databasen till.
Metod 2: Återskapa databasdata och databasfrågor när du inte har den ursprungliga databasen som inte är säker
Om du inte har en kopia av den ursprungliga databas som inte är säker i dess ursprungliga format och har försökt med vanliga felsökningsmetoder kan du försöka återställa databasdata och databasfrågor. Gör så här:
Gör en säkerhetskopia av den ursprungliga databasen.
Starta Access 2000 eller en senare version.
Access 2000, Access 2002 eller Access 2003
- Klicka på Tom Access-databas, skriv det nya databasnamnet i rutan Filnamn och klicka sedan på Skapa.
Access 2007
- Klicka Office, klicka på Ny, klicka på Tom databas och klicka sedan på Skapa för att skapa en ny tom databas.
Access 2000, Access 2002 eller Access 2003
- Klicka på Modul på Infoga-menyn. Microsoft Visual Basic Editor startas och en ny modul skapas.
Access 2007
- På fliken Skapa klickar du på nedpilen under Makro och klickar sedan på Modul. Microsoft Visual Basic Editor startas och en ny modul skapas.
Klicka på Referenser på Verktyg-menyn.
Leta reda på Microsoft DAO 3.6-objektbibliotek i listan Tillgängliga referenser och markera kryssrutan Microsoft DAO 3.6-objektbibliotek genom att klicka.
Anteckning
DAO 3.6 är också tillgänglig på Windows XP Home Edition.
Stäng dialogrutan Referenser genom att klicka på OK.
Klistra in följande kod i den nya modulen du skapade.
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 SubAnteckning
Koden försöker importera alla tabeller och alla frågor från den skadade databasen till den aktuella databasen. Ersätt
C:\My Documents\yourDatabase.mdbmed rätt sökväg och filnamn för databasen.Om du vill köra koden klickar du på Kör under-/användarformulär på menyn Kör.
Metod 3: Återskapa databasdata när du inte har den ursprungliga skyddade databasen
Om du inte har en kopia av den ursprungliga skyddade databasen i dess ursprungliga format och har försökt med standardtekniker för felsökning av skadade filer kan du försöka återställa databasdata. Gör så här:
Gör en säkerhetskopia av den ursprungliga databasen.
Starta Access 2000 eller en senare version.
Access 2000, Access 2002 eller Access 2003
- Klicka på Tom Access-databas, skriv det nya databasnamnet i rutan Filnamn och klicka sedan på Skapa.
Access 2007
- Klicka på Microsoft Office, klicka på Ny, klicka på Tom databas och klicka sedan på Skapa för att skapa en ny tom databas.
Access 2000, Access 2002 eller Access 2003
- Klicka på Modul på Infoga-menyn. Microsoft Visual Basic Editor startas och en ny modul skapas.
Access 2007
- På fliken Skapa klickar du på nedpilen under Makro och klickar sedan på Modul. Microsoft Visual Basic Editor startas och en ny modul skapas.
Klicka på Referenser på Verktyg-menyn.
Leta reda på Microsoft DAO 3.6-objektbibliotek i listan Tillgängliga referenser och markera kryssrutan Microsoft DAO 3.6-objektbibliotek genom att klicka.
Stäng dialogrutan Referenser genom att klicka på OK.
Klistra in följande kod i den nya modulen du skapade.
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 FunctionAnteckning
Koden försöker importera alla tabeller från den skadade databasen till en säkerhetskopia. Byt ut variablerna i tabellen efter steg 10 mot databasfilplatserna och användarinställningarna.
Välj BackupSecureDatabase i listan över funktioner.
Om du vill köra koden klickar du på Kör under-/användarformulär på menyn Kör.
Variabel Beskrivning strSecurePathToDatabasePlats för säker databasfil strSecurePathToWorkgroupFilePlats för arbetsgruppsfil strSecureUserInloggningsnamn för skyddad användare strSecurePwdSkyddat inloggningslösenord för användare strTempPathToDatabasePlats för tillfällig databasfil strBackupPathToDatabasePlats för säkerhetskopian av databasfilen strLogPathPlats för loggfilen
Status
Microsoft har bekräftat att det är ett problem i de Microsoft-produkter som listas i avsnittet "Gäller för".
Mer information
Mer information om hur du felsöker skador i en Microsoft Access-databas finns i följande artikel: