Access VBAの極致:DAO TableDefによる「使い捨て」一時テーブルの完全制御
Access開発において、多くのエンジニアが「クエリの積み重ね」や「安易な永続テーブル」で凌いでいる複雑な計算処理。しかし、高負荷なバッチ処理や多人数接続環境において、それはシステムを疲弊させる「負債」に他ならない。
真のアーキテクトは、計算の瞬間にのみ存在し、処理完了と同時に物理的痕跡を消し去る「動的一時テーブル」を構築する。DAOの`TableDef`を極限まで掌握し、メモリとエンジンへの負荷を最小化する設計パターンをここに記す。
—
1. なぜ「一時テーブル」を動的生成すべきか
永続的な「T_Work_XXXX」テーブルを使い回すことは、以下のリスクを孕む。
- 断片化の蓄積: 頻繁なレコードの追加・削除は、MDB/ACCDBファイルの内部断片化を加速させ、BLOB領域の肥大化を招く。
- 競合のリスク: マルチユーザー環境で同一テーブルを参照すれば、ロック競合や予期せぬデータ混入の温床となる。
- スキーマの固定化: 構造が固定されていると、計算ロジックの変更に追従できず、結局「使われていないフィールド」がゴミとして残る。
「必要なときに作り、用が済めば消す」。 これがDAO制御における唯一の正解だ。
—
2. 極限のライフサイクル管理:実装パターン
以下のコードは、DAOを用いて動的にテーブルを定義し、処理終了後に確実に破棄する堅牢なクラス構造の雛形である。
Option Compare Database
Option Explicit
‘ 一時テーブルのライフサイクルを完結させるクラス
‘ 処理終了時に自動的にテーブルを削除するRAIIパターンを意識
Public Sub ExecuteComplexProcess()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim tableName As String
Set db = CurrentDb
tableName = “tmp_Calc_” & Format(Now, “hhnnss”) & “_” & GetTickCount()
On Error GoTo Cleanup
‘ 1. テーブル定義の生成
Set tdf = db.CreateTableDef(tableName)
With tdf
.Fields.Append .CreateField(“ID”, dbLong)
.Fields.Append .CreateField(“ResultVal”, dbDouble)
db.TableDefs.Append tdf
End With
‘ 2. データの投入と計算処理
‘ ここで複雑なDAO操作を行う
MsgBox “計算処理完了。テーブル: ” & tableName
Cleanup:
‘ 3. 強制的な破棄とクリーンアップ
If Not tdf Is Nothing Then
db.TableDefs.Delete tableName
db.TableDefs.Refresh
End If
‘ オブジェクトの明示的解放(VBAのメモリ管理を信じすぎない)
Set tdf = Nothing
Set db = Nothing
End Sub
‘ 衝突を避けるための高精度な識別子生成
Private Declare PtrSafe Function GetTickCount Lib “kernel32” () As Long
—
3. シニアエンジニアが押さえるべき「3つの鉄則」
① GetTickCountによる名前空間の分離
マルチユーザー環境下では、`Now`だけでは衝突する可能性がある。Windows APIの`GetTickCount`や`CoCreateGuid`を用いて、ミリ秒単位でユニークな名前を動的に生成せよ。これにより、複数インスタンスが同時に動いても衝突は発生しない。
② 明示的なRefreshとオブジェクト解放
DAOの`TableDefs.Append`や`Delete`を実行した後は、必ず`Refresh`を呼び出すこと。これを怠ると、Accessのキャッシュと実態が乖離し、後続の処理で「テーブルが存在しません」という不可解なエラーに見舞われることになる。また、`Set = Nothing`は単なる儀式ではない。循環参照を防ぎ、VBAのガベージコレクションを正しく機能させるための境界確定である。
③ インデックスの動的制御
一時テーブルに対して複雑な結合を行う場合は、テーブル生成後に`Index`オブジェクトを追加せよ。
Dim idx As DAO.Index
Set idx = tdf.CreateIndex(“PK_ID”)
idx.Fields.Append idx.CreateField(“ID”)
idx.Primary = True
tdf.Indexes.Append idx
クエリの最適化は、クエリ自体ではなく「データ構造」から始まる。一時テーブルを使いこなせれば、複雑な計算も一瞬で終わる。
—
結論:アーキテクチャの品格
Accessはレガシーではない。使い手次第で、それは極めて強力なインメモリDBエンジンへと変貌する。
一時テーブルを「使い捨て」にする設計は、単なるコードテクニックではなく、「システムにゴミを蓄積させない」というエンジニアの哲学そのものである。常にクリーンな状態を保ち、処理が終わればその場に何も残さない。この徹底した潔さが、10年後も安定して稼働し続けるシステムの絶対条件である。
さあ、その場しのぎのテーブルを捨て、DAOのポテンシャルを解放せよ。それが次のステージへの切符だ。
