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

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

元の KB 番号: 888634

注:

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

現象

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

データベースが予期しない状態になっています

原因

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

解決方法

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

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

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

Access 2000、Access 2002、または Access 2003

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

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

  3. [ツール] メニューの [データベース ユーティリティ]、[データベースの変換]、[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 データベース] をクリックし、[ファイル名] ボックスに新しいデータベース名を入力して、[作成] をクリックします。

    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 オブジェクト ライブラリ] を見つけ、[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 オブジェクト ライブラリ] を見つけ、[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 Access データベースの破損のトラブルシューティング方法の詳細については、次の記事を参照してください。

データベースを圧縮して修復する