Erro "A base de dados está num estado inesperado" ao abrir uma base de dados no Access

Este artigo corrige um problema que ocorre quando utiliza a biblioteca DAO para converter uma base de dados.

Número original da BDC: 888634

Nota

Este artigo aplica-se a um ficheiro de base de dados do Microsoft Access (.mdb) ou a um ficheiro de base de dados do Microsoft Access (.accdb). Necessita de competências básicas de macro, programação e interoperabilidade.

Sintomas

Quando tenta abrir uma base de dados localizada no Microsoft Access 2000, ou numa versão posterior, recebe a seguinte mensagem de erro:

A base de dados encontra-se num estado inesperado

Causa

Este problema pode ocorrer quando utiliza a biblioteca do objeto de acesso a dados (DAO) para converter uma base de dados criada no Microsoft Access 97 ou numa versão anterior através do métodoCompactDatabase. O método CompactDatabase pode deixar a nova base de dados num estado parcialmente convertido.

Resolução

Para contornar este problema, utilize um dos métodos seguintes.

Método 1: utilizar o comando Converter base de dados quando tiver a base de dados original

Se ainda tiver uma cópia da base de dados original no formato original, utilize o comandoConvert Database. Para tal, siga estes passos:

Access 2000, Access 2002, ou Access 2003

  1. Faça uma cópia de segurança da base de dados original.

  2. Inicie o Access 2000 ou uma versão posterior.

  3. No menu Ferramentas, clique em Utilitários de base de dados, clique em Converter base de dados e, em seguida, clique em Para o formato de ficheiro do Access 2000.

    Nota

    Se estiver a utilizar o Access 2000, apenas é mostrada Para a versão atual da base de dados do Access no menu Converter Base de Dados.

  4. Na caixa de diálogo Base de dados para converter de, clique no nome do ficheiro da base de dados que pretende converter e, em seguida, clique em Converter.

  5. Na caixa de diálogo Converter base de dados em, escreva o novo nome do ficheiro da base de dados e, em seguida, clique em Guardar.

Access 2007

  1. Faça uma cópia de segurança da base de dados original.
  2. Tente abrir essa base de dados.
  3. Quando abre uma base de dados com o formato de ficheiro .mdb do Access 97 ou Access 95, o Access apresenta a caixa de diálogo Melhoramento da Base de Dados. Ser-lhe-á pedido para atualizar a base de dados.
  4. Clique em Sim para atualizar a base de dados para o formato de ficheiro que selecionou como formato de ficheiro predefinido no Access 2007. Após converter a base de dados, pode fazer alterações de estrutura ao ficheiro no Access 2007. No entanto, já não pode abrir a base de dados ao utilizar uma versão do Access anterior à versão para a qual converteu a base de dados.

Método 2: recuperar os dados da base de dados e as consultas da base de dados quando não tem a base de dados não protegida original

Se não tiver uma cópia da base de dados não protegida original no seu formato original e tiver experimentado técnicas de resolução de problemas padrão para a corrupção, tente recuperar os dados da base de dados e as consultas da base de dados. Para tal, siga estes passos:

  1. Faça uma cópia de segurança da base de dados original.

  2. Inicie o Access 2000 ou uma versão posterior.

  3. Access 2000, Access 2002, ou Access 2003

    • Clique em Base de dados do Access vazia, escreva o novo nome da base de dados na caixa Nome do ficheiro e, em seguida, clique em Criar.

    Access 2007

    • Clique no botão do Office, clique em Novo, clique em Base de dados vazia e, em seguida, clique em Criar para criar uma nova base de dados em branco.
  4. Access 2000, Access 2002, ou Access 2003

    • No menu Inserir, clique em Módulo. O Microsoft Visual Basic Editor é iniciado e é criado um novo módulo.

    Access 2007

    • No separador Criar, clique na seta para baixo abaixo de Macro e, em seguida, clique em Módulo. O Microsoft Visual Basic Editor é iniciado e é criado um novo módulo.
  5. No menu Ferramentas, clique em Referências.

  6. Na lista Referências disponíveis, localize Biblioteca de objetos do Microsoft DAO 3.6 e, em seguida, clique para selecionar a caixa de verificação Biblioteca de objetos do Microsoft DAO 3.6.

    Nota

    O DAO 3.6 também está disponível no Windows XP Home Edition.

  7. Para fechar a caixa de diálogo Referências, clique em OK.

  8. Cole o seguinte código no novo módulo que criou.

    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

    O código tentará importar todas as tabelas e todas as consultas da base de dados corrompida para a base de dados atual. Substitua C:\My Documents\yourDatabase.mdb pelo caminho e nome de ficheiro corretos da sua base de dados.

  9. Para executar o código, clique em Executar Sub/FormulárioDeUtilizador no menu Executar.

Método 3: recuperar os dados da base de dados quando não tem a base de dados original protegida

Se não tiver uma cópia da base de dados protegida original no seu formato original e tiver tentado técnicas de resolução de problemas padrão da corrupção, tente recuperar os dados da base de dados. Para tal, siga estes passos:

  1. Faça uma cópia de segurança da base de dados original.

  2. Inicie o Access 2000 ou uma versão posterior.

  3. Access 2000, Access 2002, ou Access 2003

    • Clique em Base de dados do Access vazia, escreva o novo nome da base de dados na caixa Nome do ficheiro e, em seguida, clique em Criar.

    Access 2007

    • Clique no botão Microsoft Office, clique em Novo, clique em Base de dados vazia e, em seguida, clique em Criar para criar uma nova base de dados vazia.
  4. Access 2000, Access 2002, ou Access 2003

    • No menu Inserir, clique em Módulo. O Microsoft Visual Basic Editor é iniciado e é criado um novo módulo.

    Access 2007

    • No separador Criar, clique na seta para baixo abaixo de Macro e, em seguida, clique em Módulo. O Microsoft Visual Basic Editor é iniciado e é criado um novo módulo.
  5. No menu Ferramentas, clique em Referências.

  6. Na lista Referências disponíveis, localize Biblioteca de objetos do Microsoft DAO 3.6 e, em seguida, clique para selecionar a caixa de verificação Biblioteca de objetos do Microsoft DAO 3.6.

  7. Para fechar a caixa de diálogo Referências, clique em OK.

  8. Cole o seguinte código no novo módulo que criou.

    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

    O código tentará importar todas as tabelas da base de dados corrompida para uma base de dados de cópia de segurança. Substitua as variáveis na tabela após o passo 10 com as localizações dos seus ficheiros de base de dados e as definições de utilizador.

  9. Na lista de funções, selecione BackupSecureDatabase.

  10. Para executar o código, clique em Executar Sub/FormulárioDeUtilizador no menu Executar.

    Variável Descrição
    strSecurePathToDatabase Localização do ficheiro de base de dados protegido
    strSecurePathToWorkgroupFile Localização do ficheiro de grupo de trabalho
    strSecureUser Nome de início de sessão de utilizador seguro
    strSecurePwd Palavra-passe de início de sessão de utilizador segura
    strTempPathToDatabase Localização do ficheiro de base de dados temporário
    strBackupPathToDatabase Localização da cópia de segurança do ficheiro da base de dados
    strLogPath Localização do ficheiro de registo

Estado

A Microsoft confirmou que este problema ocorre nos produtos da Microsoft listados na secção "Aplica-se a".

Mais Informações

Para obter mais informações sobre como resolver problemas de corrupção numa base de dados do Microsoft Access, consulte o seguinte artigo:

Compactar e reparar uma base de dados