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
元のデータベースのバックアップ コピーを作成します。
Access 2000 以降のバージョンを起動します。
[ツール] メニューの [データベース ユーティリティ]、[データベースの変換]、[Access 2000 ファイル形式] の順にクリックします。
注:
Access 2000 を使用している場合、[データベースの変換] メニューには [変換] のみが表示されます。
[変換元データベース] ダイアログ ボックスで、変換するデータベース ファイル名をクリックし、[変換] をクリックします。
[変換先データベース] ダイアログ ボックスで、データベース ファイルの新しい名前を入力し、[保存] をクリックします。
Access 2007
- 元のデータベースのバックアップ コピーを作成します。
- そのデータベースを開きます。
- Access 97 または Access 95 ファイル形式の .mdb データベースを開くと、Access は [データベースの拡張] ダイアログ ボックスを表示します。 データベースのアップグレードを求めるメッセージが表示されます。
- [はい] をクリックして、Access 2007 で既定のファイル形式として選択したファイル形式にデータベースをアップグレードします。 データベースを変換した後、Access 2007 でファイルのデザインを変更できます。 ただし、データベースを変換したバージョンより前のバージョンの Access を使用してデータベースを開くことはできなくなりました。
方法 2: 元のセキュリティで保護されていないデータベースがない場合に、データベース データとデータベース クエリを回復する
元のセキュリティで保護されていない元のデータベースのコピーが元の形式でなく、標準的な破損のトラブルシューティング手法を試した場合は、データベース データとデータベース クエリを回復します。 これを行うには、次の手順を実行します。
元のデータベースのバックアップ コピーを作成します。
Access 2000 以降のバージョンを起動します。
Access 2000、Access 2002、または Access 2003
- [空の Access データベース] をクリックし、[ファイル名] ボックスに新しいデータベース名を入力して、[作成] をクリックします。
Access 2007
- [Office] ボタンをクリックし、[新規]、[空のデータベース]、[作成] の順にクリックして、新しい空のデータベースを作成します。
Access 2000、Access 2002、または Access 2003
- [挿入] メニューの [モジュール] をクリックします。 Microsoft Visual Basic Editor が起動し、新しいモジュールが作成されます。
Access 2007
- [作成] タブで、[マクロ] の下にある下矢印をクリックし、[モジュール] をクリックします。 Microsoft Visual Basic Editor が起動し、新しいモジュールが作成されます。
[ツール] メニューの [参照設定] をクリックします。
[使用できる参照] リストで、[Microsoft DAO 3.6 オブジェクト ライブラリ] を見つけ、[Microsoft DAO 3.6 オブジェクト ライブラリ] チェック ボックスをクリックしてオンにします。
注:
DAO 3.6 は、Windows XP Home Edition でも使用できます。
[参照設定] ダイアログボックスを閉じるには、[OK] をクリックします。
作成した新しいモジュールに次のコードを貼り付けます。
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
をデータベースの正しいパスとファイル名に置き換えます。コードを実行するには、[実行] メニューの [Sub/ユーザー フォームの実行] をクリックします。
方法 3: 元のセキュリティで保護されたデータベースがない場合に、データベース データを回復する
元のセキュリティで保護されたデータベースのコピーが元の形式でなく、標準的な破損のトラブルシューティング手法を試した場合は、データベース データを回復します。 これを行うには、次の手順を実行します。
元のデータベースのバックアップ コピーを作成します。
Access 2000 以降のバージョンを起動します。
Access 2000、Access 2002、または Access 2003
- [空の Access データベース] をクリックし、[ファイル名] ボックスに新しいデータベース名を入力して、[作成] をクリックします。
Access 2007
- [Microsoft Office] ボタンをクリックし、[新規]、[空のデータベース]、[作成] の順にクリックして、新しい空のデータベースを作成します。
Access 2000、Access 2002、または Access 2003
- [挿入] メニューの [モジュール] をクリックします。 Microsoft Visual Basic Editor が起動し、新しいモジュールが作成されます。
Access 2007
- [作成] タブで、[マクロ] の下にある下矢印をクリックし、[モジュール] をクリックします。 Microsoft Visual Basic Editor が起動し、新しいモジュールが作成されます。
[ツール] メニューの [参照設定] をクリックします。
[使用できる参照] リストで、[Microsoft DAO 3.6 オブジェクト ライブラリ] を見つけ、[Microsoft DAO 3.6 オブジェクト ライブラリ] チェック ボックスをクリックしてオンにします。
[参照設定] ダイアログボックスを閉じるには、[OK] をクリックします。
作成した新しいモジュールに次のコードを貼り付けます。
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 の後にある表の変数を、データベース ファイルの場所とユーザー設定に置き換えます。
関数のリストで、[BackupSecureDatabase] を選択します。
コードを実行するには、[実行] メニューの [Sub/ユーザー フォームの実行] をクリックします。
変数 説明 strSecurePathToDatabase
セキュリティで保護されたデータベース ファイルの場所 strSecurePathToWorkgroupFile
ワークグループ ファイルの場所 strSecureUser
セキュリティで保護されたユーザー ログオン名 strSecurePwd
セキュリティで保護されたユーザー ログオン パスワード strTempPathToDatabase
一時データベース ファイルの場所 strBackupPathToDatabase
バックアップ データベース ファイルの場所 strLogPath
ログ ファイルの場所
状態
マイクロソフトでは、この問題をこの資料の対象製品として記載されているマイクロソフト製品の問題として認識しています。
詳細情報
Microsoft Access データベースの破損のトラブルシューティング方法の詳細については、次の記事を参照してください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示