Access でデータベースを開く際に"データベースが予期しない状態にある" というエラーが表示される

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

注意

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

元の KB 番号:   888634

注意

この記事は、Microsoft 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. [ツール] メニューの [データベース ユーティリティ] クリックし、[ データベースの変換] をクリックし、[To Access 2000 ファイル形式] をクリックします

    注意

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

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

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

Access 2007

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

方法 2: 元の非保護データベースがインストールされていない場合に、データベース データとデータベース クエリを復元する

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

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

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

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

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

    Access 2007

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

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

    Access 2007

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

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

    注意

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

  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/UserForm の実行] をクリック します。

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

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

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

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

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

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

    Access 2007

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

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

    Access 2007

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

  6. [利用可能な 参照] ボックスの一覧で 、Microsoft DAO 3.6 オブジェクト ライブラリを見つけて 、[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/UserForm の実行] をクリック します。

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

状態

Microsoft は、「適用先」セクションに記載されている Microsoft 製品の問題を確認しました。

詳細情報

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

データベースのコンパクト化と修復