Access でデータベースを開くときに "データベースが予期しない状態です" というエラーが発生する

この記事では、DAO ライブラリを使用してデータベースを変換する際に発生する問題を修正します。

注意

Office 365 用リソース は、 エンタープライズ向け Microsoft 365 アプリに名前変更されています。 この変更の詳細については、 このブログの投稿を参照してください。

元の KB 番号:  888634

注意

この記事は、Microsoft Office Access データベース (.mdb) ファイルまたは Microsoft Access データベース (.accdb) ファイルに適用されます。 基本的なマクロ、コーディング、および相互運用性のスキルが必要です。

現象

Microsoft Access 2000 またはそれ以降のバージョンのデータベースを開こうとすると、次のエラーメッセージが表示されます。

データベースが予期しない状態にある

原因

この問題は、データアクセスオブジェクト (DAO) ライブラリを使用して、Microsoft Access 97 またはそれ以前のバージョンで作成したデータベースを、このメソッドを使用して変換した場合に発生することがあり CompactDatabase ます。 メソッドは、 CompactDatabase 新しいデータベースを部分的に変換された状態のままにしておくことができます。

解決方法

この問題を解決するには、次のいずれかの方法を使用します。

方法 1: 元のデータベースがある場合は、[データベースの変換] コマンドを使用します。

元のデータベースのコピーが元の形式で残っている場合は、コマンドを使用し Convert Database ます。 これを行うには、次の手順を実行します。

Access 2000、Access 2002、または Access 2003

  1. 元のデータベースのバックアップコピーを作成します。

  2. Access 2000 以降のバージョンを起動します。

  3. [ツール] メニューの [データベースユーティリティ] をクリックし、[データベースの変換] をクリックして、 2000 ファイル形式にアクセスします。

    注意

    Access 2000 を使用している場合は、[データベースの変換] メニューに現在の Access データベースのバージョンのみが表示されます。

  4. [変換元データベース] ダイアログボックスで、変換するデータベースファイル名をクリックし、[変換] をクリックします。

  5. [データベースを変換] ダイアログボックスで、データベースファイルの新しい名前を入力し、[保存] をクリックします。

Access 2007

  1. 元のデータベースのバックアップコピーを作成します。
  2. そのデータベースを開いてみます。
  3. Access 97 または Access 95 のファイル形式 .mdb データベースを開くと、[データベースの拡張] ダイアログボックスが表示されます。 データベースのアップグレードを求めるメッセージが表示されます。
  4. [はい] をクリックして、Access 2007 でデータベースを既定のファイル形式として選択したファイル形式のいずれかにアップグレードします。 データベースを変換した後、Access 2007 でファイルのデザインを変更することができます。 ただし、データベースを変換したバージョンより前のバージョンの Access を使用してデータベースを開くことはできなくなりました。

方法 2: 元の保護されていないデータベースがない場合にデータベースデータおよびデータベースクエリを復元する

元の保護されていないデータベースのコピーが元の形式でなく、標準的な破損のトラブルシューティング手法を試したことがある場合は、データベースデータとデータベースクエリを回復してください。 これを行うには、次の手順を実行します。

  1. 元のデータベースのバックアップコピーを作成します。

  2. Access 2000 以降のバージョンを起動します。

  3. Access 2000、Access 2002、または Access 2003

    • [空の Access データベース] をクリックし、[ファイル名] ボックスに新しいデータベース名を入力して、[作成] をクリックします。

    Access 2007

    • [Office] ボタンをクリックし、[新規]、[空のデータベース]、[作成] の順にクリックして、新しい空のデータベースを作成します。
  4. Access 2000、Access 2002、または Access 2003

    • [挿入] メニューの [モジュール] をクリックします。 [Microsoft Visual Basic Editor] が起動し、新しいモジュールが作成されます。

    Access 2007

    • [作成] タブで、[マクロ] の下の下矢印をクリックし、[モジュール] をクリックします。 [Microsoft Visual Basic Editor] が起動し、新しいモジュールが作成されます。
  5. [ツール] メニューの [参照設定] をクリックします。

  6. [参照可能なライブラリ] ボックスの一覧で、[ Microsoft Dao 3.6 object library] を見つけ、[ microsoft dao 3.6 オブジェクトライブラリ] チェックボックスをオンにします。

    注意

    DAO 3.6 は、Windows XP Home Edition でも利用できます。

  7. [参照設定] ダイアログボックスを閉じるには、[ OK] をクリックします。

  8. 作成した新しいモジュールに次のコードを貼り付けます。

    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
    

    注意

    このコードでは、破損したデータベースからすべてのテーブルとすべてのクエリをカレントデータベースにインポートしようとします。 を、 C:\My Documents\yourDatabase.mdb データベースの正しいパスとファイル名に置き換えます。

  9. コードを実行するには、[実行] メニューの [ Sub/ユーザーフォームの実行] をクリックします。

方法 3: セキュリティで保護された元のデータベースがない場合にデータベースデータを復元する

元のセキュリティで保護されたデータベースのコピーが元の形式でなく、標準的な破損のトラブルシューティング手法を試したことがある場合は、データベースデータを回復するようにしてください。 これを行うには、次の手順を実行します。

  1. 元のデータベースのバックアップコピーを作成します。

  2. Access 2000 以降のバージョンを起動します。

  3. Access 2000、Access 2002、または Access 2003

    • [空の Access データベース] をクリックし、[ファイル名] ボックスに新しいデータベース名を入力して、[作成] をクリックします。

    Access 2007

    • Microsoft Office ボタンをクリックし、[新規]、[空のデータベース]、[作成] の順にクリックして、新しい空のデータベースを作成します。
  4. Access 2000、Access 2002、または Access 2003

    • [挿入] メニューの [モジュール] をクリックします。 [Microsoft Visual Basic Editor] が起動し、新しいモジュールが作成されます。

    Access 2007

    • [作成] タブで、[マクロ] の下の下矢印をクリックし、[モジュール] をクリックします。 [Microsoft Visual Basic Editor] が起動し、新しいモジュールが作成されます。
  5. [ツール] メニューの [参照設定] をクリックします。

  6. [参照可能なライブラリ] ボックスの一覧で、[ Microsoft Dao 3.6 object library] を見つけ、[ microsoft dao 3.6 オブジェクトライブラリ] チェックボックスをオンにします。

  7. [参照設定] ダイアログボックスを閉じるには、[ OK] をクリックします。

  8. 作成した新しいモジュールに次のコードを貼り付けます。

    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
    

    注意

    このコードでは、破損したデータベースのすべてのテーブルをバックアップデータベースにインポートしようとしています。 手順10の後の表の変数を、使用しているデータベースファイルの場所とユーザー設定に置き換えます。

  9. 関数の一覧で、[ Backupsecuredatabase] を選択します。

  10. コードを実行するには、[実行] メニューの [ Sub/ユーザーフォームの実行] をクリックします。

    変数 説明
    strSecurePathToDatabase セキュリティで保護されたデータベースファイルの場所
    strSecurePathToWorkgroupFile ワークグループファイルの場所
    strSecureUser セキュリティで保護されたユーザーログオン名
    strSecurePwd セキュリティで保護されたユーザーログオンパスワード
    strTempPathToDatabase 一時データベースファイルの場所
    strBackupPathToDatabase バックアップデータベースファイルの場所
    strLogPath ログファイルの場所

状態

Microsoft では、この問題は、「適用先」に記載されているマイクロソフト製品の問題であることを確認しています。

詳細情報

Microsoft Office Access データベースで破損のトラブルシューティングを行う方法の詳細については、次の記事を参照してください。

データベースを最適化および修復する