Error “La base de datos está en un estado inesperado” al abrir una base de datos en Access

En este artículo se corrige un problema que se produce al usar la biblioteca DAO para convertir una base de datos.

Número KB original: 888634

Nota:

Este artículo se aplica a un archivo de base de datos de Microsoft Access .mdb o .accdb. Requiere conocimientos básicos de macros, codificación e interoperabilidad.

Síntomas

Cuando intenta abrir una base de datos en Microsoft Access 2000 o una versión posterior, recibe el mensaje de error siguiente:

La base de datos está en un estado inesperado

Causa

Este problema puede producirse cuando se usa la biblioteca de objetos de acceso a datos (DAO) para convertir una base de datos creada en Microsoft Access 97 o una versión anterior mediante el métodoCompactDatabase. El método CompactDatabase puede dejar la nueva base de datos en un estado parcialmente convertido.

Solución

Para resolver el problema, use uno de los siguientes métodos.

Método 1: Use el comando Convertir base de datos cuando tenga la base de datos original

Si aún tiene una copia de la base de datos original en su formato original, use el comandoConvert Database. Para ello, siga estos pasos:

Access 2000, Access 2002 o Access 2003

  1. Haga una copia de seguridad de la base de datos original.

  2. Inicie Access 2000 o una versión posterior.

  3. En el menú Herramientas, haga clic en Utilidades de la base de datos, en Convertir base de datos y, a continuación, en A formato de archivo de Access 2000.

    Nota:

    Si usa Access 2000, solo aparece A la versión de base de datos actual de Access en el menú Convertir base de datos.

  4. En el cuadro de diálogo Base de datos a convertir, haga clic en el nombre del archivo de base de datos que desea convertir y, a continuación, en Convertir.

  5. En el cuadro de diálogo Convertir la base de datos en, escriba el nuevo nombre del archivo de base de datos y, a continuación, haga clic en Guardar.

Access 2007

  1. Haga una copia de seguridad de la base de datos original.
  2. Intente abrir esa base de datos.
  3. Al abrir una base de datos .mdb con formato de archivo de Access 97 o Access 95, Access muestra el cuadro de diálogo Mejoras de base de datos. Se le pedirá que actualice la base de datos.
  4. Haga clic en para actualizar la base de datos al formato de archivo que haya seleccionado como predeterminado en Access 2007. Después de convertir la base de datos, puede realizar cambios de diseño en el archivo en Access 2007. Sin embargo, ya no puede abrir la base de datos mediante una versión de Access anterior a la versión a la que convirtió la base de datos.

Método 2: Recuperar los datos y las consultas de la base de datos cuando no tiene la original no segura

Si no tiene una copia de la base de datos no segura original en su formato primigenio y ha probado técnicas de solución de problemas por daños estándar, intente recuperar los datos y las consultas de la base de datos. Para ello, siga estos pasos:

  1. Haga una copia de seguridad de la base de datos original.

  2. Inicie Access 2000 o una versión posterior.

  3. Access 2000, Access 2002 o Access 2003

    • Haga clic en Base de datos en blanco de Access, escriba el nuevo nombre de la base de datos en el cuadro Nombre de archivo y, a continuación, haga clic en Crear.

    Access 2007

    • Haga clic en el botón de Office, en Nuevo, en Base de datos en blanco y, a continuación, en Crear para crear una nueva base de datos en blanco.
  4. Access 2000, Access 2002 o Access 2003

    • En el menú Insertar, haga clic en Módulo. Se inicia el Editor de Visual Basic de Microsoft y se crea un nuevo módulo.

    Access 2007

    • En la pestaña Crear, haga clic en la flecha abajo de Macro y, a continuación, en Módulo. Se inicia el Editor de Visual Basic de Microsoft y se crea un nuevo módulo.
  5. En el menú Herramientas, haga clic en Referencias.

  6. En la lista Referencias disponibles, busque Microsoft DAO 3.6 Object Library (Biblioteca de objetos de Microsoft DAO 3.6) y, a continuación, haga clic para seleccionar la casilla Microsoft DAO 3.6 Object Library (Biblioteca de objetos de Microsoft DAO 3.6).

    Nota:

    DAO 3.6 también está disponible en Windows XP Home Edition.

  7. Para cerrar el cuadro de diálogo Referencias, haga clic en Aceptar.

  8. Pegue el siguiente código en el nuevo módulo que ha creado.

    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
    

    Nota:

    El código intentará importar todas las tablas y las consultas de la base de datos dañada a la actual. Reemplace C:\My Documents\yourDatabase.mdb por la ruta de acceso y el nombre de archivo correctos de la base de datos.

  9. Para ejecutar el código, haga clic en Ejecutar Sub/UserForm en el menú Ejecutar.

Método 3: Recuperar los datos de la base de datos cuando no tiene la original segura

Si no tiene una copia de la base de datos protegida original en su formato primigenio y ha probado técnicas de solución de problemas por daños estándar, intente recuperar los datos de la base de datos. Para ello, siga estos pasos:

  1. Haga una copia de seguridad de la base de datos original.

  2. Inicie Access 2000 o una versión posterior.

  3. Access 2000, Access 2002 o Access 2003

    • Haga clic en Base de datos en blanco de Access, escriba el nuevo nombre de la base de datos en el cuadro Nombre de archivo y, a continuación, haga clic en Crear.

    Access 2007

    • Haga clic en el botón de Microsoft Office, en Nuevo, en Base de datos en blanco y, a continuación, en Crear para crear una nueva base de datos en blanco.
  4. Access 2000, Access 2002 o Access 2003

    • En el menú Insertar, haga clic en Módulo. Se inicia el Editor de Visual Basic de Microsoft y se crea un nuevo módulo.

    Access 2007

    • En la pestaña Crear, haga clic en la flecha abajo de Macro y, a continuación, en Módulo. Se inicia el Editor de Visual Basic de Microsoft y se crea un nuevo módulo.
  5. En el menú Herramientas, haga clic en Referencias.

  6. En la lista Referencias disponibles, busque Microsoft DAO 3.6 Object Library (Biblioteca de objetos de Microsoft DAO 3.6) y, a continuación, haga clic para seleccionar la casilla Microsoft DAO 3.6 Object Library (Biblioteca de objetos de Microsoft DAO 3.6).

  7. Para cerrar el cuadro de diálogo Referencias, haga clic en Aceptar.

  8. Pegue el siguiente código en el nuevo módulo que ha creado.

    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
    

    Nota:

    El código intentará importar todas las tablas de la base de datos dañada a una base de datos de copia de seguridad. Reemplace las variables de la tabla después del paso 10 por las ubicaciones de los archivos de base de datos y su configuración de usuario.

  9. En la lista de funciones, seleccione BackupSecureDatabase.

  10. Para ejecutar el código, haga clic en Ejecutar Sub/UserForm en el menú Ejecutar.

    Variable Descripción
    strSecurePathToDatabase Ubicación del archivo de base de datos segura
    strSecurePathToWorkgroupFile Ubicación del archivo de grupo de trabajo
    strSecureUser Nombre de inicio de sesión de usuario seguro
    strSecurePwd Contraseña de inicio de sesión de usuario segura
    strTempPathToDatabase Ubicación del archivo de base de datos temporal
    strBackupPathToDatabase Ubicación del archivo de base de datos de copia de seguridad
    strLogPath Ubicación del archivo de registro

Estado

Microsoft ha confirmado que se trata de un problema de los productos de Microsoft enumerados en la sección "Se aplica a".

Más información

Para obtener más información acerca de cómo solucionar daños en una base de datos de Microsoft Access, consulte el siguiente artículo:

Compactar y reparar una base de datos