外部のデータベースファイル内にあるテーブルをリンクテーブルとしているデータベースにおいて、そのモジュール内のプログラムを使ってリンク先のデータベースファイルを最適化するプログラムの例です。
ここでは、リンクテーブルのうちのある1つのテーブルの定義を参照してリンク先のデータベースファイルのフルパスを取得、それに対して最適化処理を行っています。
Public Sub CompactSample()
Dim dbs As Database
Dim tdf As TableDef
Dim strDataDB As String
Dim strDataDBDir As String
Dim strDataDBTmp As String
On Error GoTo Err_Handler
Set dbs = CurrentDb
'mtbl得意先マスタからリンク先DBのフルパスを取得
Set tdf = dbs.TableDefs("mtbl得意先マスタ")
strDataDB = Mid$(tdf.Connect, InStr(tdf.Connect, ";DATABASE=") + Len(";DATABASE="))
'リンク先DBからドライブ+フォルダ部分を取り出し
strDataDBDir = Left$(strDataDB, InStrRev(strDataDB, "\"))
'一時的に最適化先となるファイルを設定
strDataDBTmp = strDataDBDir & "db1.accdb"
'最適化の実行
DBEngine.CompactDatabase strDataDB, strDataDBTmp
'元のファイルを削除
Kill strDataDB
'最適化先のファイル名を元のファイル名にリネーム
Name strDataDBTmp As strDataDB
Exit_Here:
Exit Sub
Err_Handler:
Select Case Err.Number
Case 3704
Beep
MsgBox "他のユーザーがデータDBを使用しているため最適化できませんでした!", _
vbOKOnly + vbExclamation
Case Else
Beep
MsgBox "エラー番号:" & Err.Number & vbCrLf & _
"エラー内容:" & Err.Description, _
vbOKOnly + vbCritical
End Select
Resume Exit_Here:
End Sub
大きなポイントとなる最適化の処理自体は、「DBEngine.CompactDatabase」の命令1行だけです。
ただしこの命令では、「最適化するファイル」だけでなく、最適化先、つまり「最適化の結果であるサイズを小さくしたファイル」を別々に指定する必要があります。つまり、対象ファイルを直接処理するのではなく、そこから最適化されたファイルを別に作り出す処理となります。
そのため、それら2つのファイルのフルパスを設定したり、最適化されたファイル名を本来のファイル名に戻したりする付随的な処理が必要となります。
上記の例では、まず「mtbl得意先マスタ」というテーブルからリンク先のデータベースファイル名を取得し、それを変数strDataDBにセットしています。これが最適化元のファイルのフルパスです。
次に、そこからドライブ+フォルダ部分を取り出し、仮に最適化先のファイル名を「db1.accdb」として、そのフルパスを組み立てて変数strDataDBTmpに設定しています。
そして、最適化を実行し、後処理として「元のファイルを削除」→「最適化先のファイル名を元のファイル名にリネーム」という2ステップの処理を行うことで、最適化結果の「db1.accdb」というファイルを本来のファイル名に戻し、結果あたかもリンク先のデータベースファイルが小さくなったかのような状態にします。
実行例:
ここでは、リンク先のファイルが「Database1.accdb」であり、上記のプログラムを実行した場合にファイルがどのように遷移するかを、プログラムをステップ実行させて図示しています。
- 実行前の状態(大きなサイズのDatabase1.accdbがある)
- 最適化を実行(Database1.accdbと、サイズの小さくなったdb1.accdbの2つがある)
- 元のファイルを削除(db1.accdbだけとなる)
- ファイルをリネーム(小さなサイズのDatabase1.accdbだけとなる)
補足
多くの場合、リンクテーブルを使うということは、そのテーブルを複数のユーザー(アプリケーション・データベース)で共有する形になっていると思います。他のユーザーがまだそのデータベースを利用している状態で上記のプログラムを実行すると、エラーが発生して、最適化することはできません。
そこで上記ではエラーをトラップし、エラー番号3704が発生したときには警告メッセージを表示させるようにしています。
しかし、他のユーザーが単にアプリケーション・データベースを開いているだけで、画面にデータを表示させるなどしてテーブルにアクセスしていない状況ではエラーは起こりません。
とはいえ、いつテーブルにアクセスし始めるか分かりませんので、微妙なタイミングで両者の操作が重なった場合にはどのような不都合が生じるか分かりません。運用上で重ならないようにしたり、何らかの手段で他の利用者をチェックしたり、安全策を講じることが必要かもしれません。もちろん、 上記のプログラムを実行する際はそのデータベース自身がリンクテーブルを開いていないことが大前提となります。
|