【実務・中級編】「クエリの保存」を最小限にする:QueryDefを一時オブジェクトとして作成・削除するメモリ管理術 – Access VBA解析バイブル

スポンサーリンク

Accessの「ゴミ屋根」を解体せよ:動的QueryDefで実現する真のメモリ管理術

Access開発において、初心者が陥る最大にして最悪の罠は、「動的なSQLを走らせるために、無数のクエリ定義(QueryDef)をデータベースウィンドウに保存してしまうこと」だ。

「毎回クエリを作るのが面倒だから、とりあえず保存しておくか」
その無邪気な判断が、データベースを肥大化させ、断片化を招き、最終的にはシステム全体の腐敗を決定づける。本稿では、QueryDefを一時オブジェクトとして動的に生成・破棄する「クリーン・アーキテクチャ」の真髄を伝授する。

—

なぜ「保存されたクエリ」が害悪なのか

Accessにおいて、`CurrentDb.QueryDefs` に名前を付けて保存することは、ファイルシステム上のメタデータ領域を消費し続ける行為だ。

1. 肥大化の連鎖: コンパイル済みのクエリ定義はファイルサイズを膨らませる。
2. 名前空間の汚染: 数百ものクエリがナビゲーションウィンドウに並ぶ姿は、保守担当者への冒涜に等しい。
3. ロックと排他制御: 永続的なオブジェクトは、予期せぬタイミングでロック競合の原因となる。

プロフェッショナルな設計において、「実行時のみ存在し、終われば消滅する」のがSQLの本来あるべき姿だ。

—

実装パターン:一時的QueryDefによるパラメーター注入

名前を空文字 `””` にして `CreateQueryDef` を呼び出すと、Accessはそれを「一時的なQueryDef」としてメモリ空間にのみ生成する。これを活用すれば、データベースの物理構造を汚すことなく、堅牢なパラメータークエリを実行できる。

プロダクションコード:動的QueryDef実行エンジン

このプロシージャは、SQLインジェクションを回避しつつ、メモリを一切残さない洗練されたパターンだ。

Public Sub ExecuteDynamicQuery(ByVal sqlText As String, ParamArray params() As Variant)
Dim qdf As DAO.QueryDef
Dim i As Integer

‘ 一時的なQueryDefを作成(名前を空にするとメモリ上にのみ生成される)
Set qdf = CurrentDb.CreateQueryDef(“”, sqlText)

On Error GoTo Cleanup

‘ パラメーターのバインド
‘ 順序依存になるが、クエリのSQL内でパラメーター順を制御する
For i = LBound(params) To UBound(params)
qdf.Parameters(i).Value = params(i)
Next i

‘ クエリの実行(アクションクエリの場合)
‘ 抽出結果が必要なら OpenRecordset を使用すること
qdf.Execute dbFailOnError

Cleanup:
‘ 重要な処理:明示的な解放
‘ Closeを呼び出すことで、メモリとリソースを即座に解放する
If Not qdf Is Nothing Then
qdf.Close
Set qdf = Nothing
End If

If Err.Number <> 0 Then
Err.Raise Err.Number, “ExecuteDynamicQuery”, “クエリ実行エラー: ” & Err.Description
End If
End Sub

—

この設計の「神髄」を理解する

1. なぜ `dbFailOnError` を使うのか

DAOにおいて `Execute` メソッドにこの定数を渡さないことは、エラーを握りつぶすのと同じだ。トランザクションの整合性を保つための「最低限の礼儀」として、常に付与すること。

2. メモリリークを許さない `Cleanup` パターン

VBAはガベージコレクションが強力ではない。`Set qdf = Nothing` だけでは不十分な場合がある。必ず `qdf.Close` を先行させ、リソースのハンドルをOSに返却してから参照を破棄する。これが「メモリ管理を知り尽くした者」の作法だ。

3. パラメータークエリの優位性

文字列結合でSQLを組み立てるコードは、SQLインジェクションの脆弱性だけでなく、型変換エラーの温床となる。`Parameters` コレクションを使用することで、Accessのエンジンが型を正しく解釈し、最適化されたクエリプランを生成する。

—

現場で戦う開発者への提言

この手法を導入するだけで、君のAccessデータベースは数倍「軽く」、そして「堅牢」になる。

  • 保守性: クエリ名を考える必要がない。コードを見れば何をしているか明白だ。
  • 堅牢性: 名前衝突がないため、マルチユーザー環境や、バックエンドDB(SQL Server等)への移行時にも構造的な変更が最小限で済む。

「保存する」という怠惰を捨て、「生成し、使い、消す」という規律を持つこと。それが、Accessという老練なツールを限界まで使いこなすための唯一の道だ。

さあ、今すぐ君のプロジェクトから、使われていない無数の「残骸クエリ」を削除し、このコードで置き換えてみてほしい。Accessの挙動が変わるはずだ。

タイトルとURLをコピーしました