Erreur « La base de données est dans un état inattendu » lorsque vous ouvrez une base de données dans Access

Cet article corrige un problème qui se produit lorsque vous utilisez la bibliothèque DAO pour convertir une base de données.

Numéro de l’article d’origine dans la base de connaissances : 888634

Remarque

Cet article s’applique à un fichier de base de données Microsoft Access .MDB ou .ACCDB. Vous devez disposer de connaissances de base en macro, codage et interopérabilité avant de commencer.

Symptômes

Quand vous essayez d’ouvrir une base de données dans Microsoft Access 2000 ou version ultérieure, le message d’erreur suivant s’affiche :

La base de donnée est dans un état inattendu

Cause

Ce problème peut se produire lorsque vous utilisez la bibliothèque DAO (Data Access Object) pour convertir une base de données créée dans Microsoft Access 97 ou version antérieure à l’aide de la méthodeCompactDatabase. La méthode CompactDatabase peut laisser la nouvelle base de données dans un état où elle nʼest convertie que partiellement.

Résolution

Pour résoudre ce problème, appliquez l’une des méthodes suivantes :

Méthode 1 : utiliser la commande Convertir la base de données lorsque vous disposez de la base de données originale

Si vous avez encore une copie de la base de données originale dans son format d’origine, utilisez la commandeConvert Database. Pour cela, procédez comme suit :

Access 2000, Access 2002 ou Access 2003

  1. Effectuez une copie de sauvegarde de la base de données d’origine.

  2. Démarrez Access 2000 ou une version ultérieure.

  3. Dans le menu Outils, sélectionnez Utilitaires de base de données, puis Convertir la base de données et cliquez sur Vers le format de fichiers Access 2000.

    Remarque

    Si vous utilisez Access 2000, seule lʼoption Vers la version actuelle de la base de données Access apparaît dans le menu Convertir la base de données.

  4. Dans la boîte de dialogue Convertir une base de données, cliquez sur le nom du fichier de base de données à convertir, puis cliquez sur Convertir.

  5. Dans la boîte de dialogue Convertir la base de données sous, saisissez le nouveau nom du fichier de base de données, puis cliquez sur Enregistrer.

Access 2007

  1. Effectuez une copie de sauvegarde de la base de données d’origine.
  2. Essayez ensuite d’ouvrir cette base de données.
  3. Lorsque vous ouvrez une base de données Access 97 ou Access 95 au format de fichier .mdb, Access affiche la boîte de dialogue Amélioration de la base de données. Vous êtes invité à mettre à niveau la base de données.
  4. Cliquez sur Oui pour mettre à niveau la base de données vers le format de fichier que vous avez défini par défaut dans Access 2007. Une fois la base de données convertie, vous pouvez apporter des modifications de conception au fichier dans Access 2007. Toutefois, vous ne pouvez plus ouvrir la base de données avec une version d’Access antérieure à celle vers laquelle vous avez converti la base de données.

Méthode 2 : récupérer les données et requêtes de la base de données lorsque vous ne disposez pas de la base de données originale non sécurisée

Si vous ne disposez pas dʼune copie de la base de données non sécurisée dans son format dʼorigine et que vous avez essayé les procédures standard de résolution des problèmes de corruption de base de données, tentez de récupérer les données et requêtes de la base de données. Pour cela, procédez comme suit :

  1. Effectuez une copie de sauvegarde de la base de données d’origine.

  2. Démarrez Access 2000 ou une version ultérieure.

  3. Access 2000, Access 2002 ou Access 2003

    • Cliquez sur Base de données Access vide, tapez le nom de la nouvelle base de données dans la zone Nom de fichier, puis cliquez sur Créer.

    Access 2007

    • Cliquez sur le bouton Office, sur Nouveau, puis sur Base de données vide et sélectionnez Créer pour créer une base de données vide.
  4. Access 2000, Access 2002 ou Access 2003

    • Dans le menu Insertion, cliquez sur Module. Microsoft Visual Basic Editor démarre et un module est créé.

    Access 2007

    • Sous l’onglet Créer, cliquez sur la flèche vers le bas sous Macro, puis sur Module. Microsoft Visual Basic Editor démarre et un module est créé.
  5. Dans le menu Outils, cliquez sur Références.

  6. Dans la liste Références disponibles, recherchez la bibliothèque d’objets Microsoft DAO 3.6, puis cochez la case Bibliothèque d’objets Microsoft DAO 3.6.

    Remarque

    DAO 3.6 est également disponible sur Windows XP Édition Familiale.

  7. Pour fermer la boîte de dialogue Références, cliquez sur OK.

  8. Collez le code suivant dans le nouveau module que vous avez créé.

    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
    

    Remarque

    Le code tente d’importer toutes les tables et toutes les requêtes de la base de données endommagée dans la base de données actuelle. Remplacez C:\My Documents\yourDatabase.mdb par le chemin d’accès et le nom de fichier corrects de votre base de données.

  9. Pour exécuter le code, cliquez sur Exécuter Sub/UserForm dans le menu Exécuter.

Méthode 3 : Récupérer les données de la base sans la base de données sécurisée d’origine

Si vous n’avez pas de copie de la base de données sécurisée d’origine dans son format d’origine et que vous avez essayé les techniques standard de résolution des problèmes d’endommagement, essayez de récupérer les données de la base. Pour cela, procédez comme suit :

  1. Effectuez une copie de sauvegarde de la base de données d’origine.

  2. Démarrez Access 2000 ou une version ultérieure.

  3. Access 2000, Access 2002 ou Access 2003

    • Cliquez sur Base de données Access vide, tapez le nom de la nouvelle base de données dans la zone Nom de fichier, puis cliquez sur Créer.

    Access 2007

    • Cliquez sur le bouton Microsoft Office puis sur Nouveau. Cliquez ensuite sur Base de données vide, puis sur Créer pour créer une base de données vide.
  4. Access 2000, Access 2002 ou Access 2003

    • Dans le menu Insertion, cliquez sur Module. Microsoft Visual Basic Editor démarre et un module est créé.

    Access 2007

    • Sous l’onglet Créer, cliquez sur la flèche vers le bas sous Macro, puis sur Module. Microsoft Visual Basic Editor démarre et un module est créé.
  5. Dans le menu Outils, cliquez sur Références.

  6. Dans la liste Références disponibles, recherchez la bibliothèque d’objets Microsoft DAO 3.6, puis cochez la case Bibliothèque d’objets Microsoft DAO 3.6.

  7. Pour fermer la boîte de dialogue Références, cliquez sur OK.

  8. Collez le code suivant dans le nouveau module que vous avez créé.

    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
    

    Remarque

    Le code tente d’importer toutes les tables de la base de données endommagée dans une base de données de sauvegarde. Remplacez les variables de la table après l’étape 10 par vos emplacements de fichiers de base de données et vos paramètres utilisateur.

  9. Dans la liste des fonctions, sélectionnez BackupSecureDatabase.

  10. Pour exécuter le code, cliquez sur Exécuter Sub/UserForm dans le menu Exécuter.

    Variable Description
    strSecurePathToDatabase Emplacement du fichier de base de données sécurisé
    strSecurePathToWorkgroupFile Emplacement du fichier de groupe de travail
    strSecureUser Nom d’utilisateur sécurisé
    strSecurePwd Mot de passe d’utilisateur sécurisé
    strTempPathToDatabase Emplacement du fichier de base de données temporaire
    strBackupPathToDatabase Emplacement du fichier de base de données de sauvegarde
    strLogPath Emplacement du fichier journal

État

Microsoft a confirmé l’existence de ce problème dans les produits Microsoft répertoriés dans la section « Produits concernés ».

Informations supplémentaires

Pour plus d’informations sur la résolution des problèmes d’endommagement de base de données Microsoft Access, consultez l’article suivant :

Compacter et réparer une base de données