【実務・中級編】CurrentDb.CreateQueryDefで一時クエリを作成し、処理後に削除する – Access VBA解析バイブル

スポンサーリンク

Access VBAの「ゴミ屋根」を脱却せよ:CreateQueryDefによる動的クエリ管理の極意

Access開発において、初心者が最初に陥る罠が「クエリの乱立」だ。
画面上のクエリタブが数十個に膨れ上がり、どれがどの処理で使われているのか誰も分からない状態――これを放置することは、データベースの寿命を縮める自殺行為に等しい。

真の業務自動化エンジニアは、「使い捨てのクエリは、コードの中で生み出し、用が済んだら静かに消す」

今回は、`CurrentDb.CreateQueryDef`を使い、複雑な集計処理をスマートに完結させるための「堅牢な設計手法」を伝授する。

1. なぜ「一時クエリ」が必要なのか?

多くのエンジニアは、SQL文をVBAの`DoCmd.RunSQL`に直接書き込むか、あるいは固定のクエリをAccess上に保存して使い回す。しかし、以下の理由からこれらは推奨されない。

  • 固定クエリの弊害: 処理のたびにクエリ名が固定されると、マルチユーザー環境や、一人のユーザーが連続して処理を行う際にロックや競合が発生する。
  • SQLの直接実行の限界: 複雑な集計や入れ子構造のSQLは、VBA内の文字列として扱うには可読性が低すぎ、メンテナンス性が皆無になる。

`CreateQueryDef`を動的に利用すれば、「その処理の瞬間だけ存在する専用の実行エンジン」をメモリ上に生成できる。これが、肥大化を防ぎ、かつパフォーマンスを最大化する唯一の解だ。

2. 堅牢な実装:プロダクションコードのテンプレート

以下に、エラーハンドリングを完備し、処理後のクリーンアップを確実に行うための「黄金のテンプレート」を示す。

Public Sub ExecuteDynamicQuery()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim qryName As String
Dim sqlText As String

‘ 一時クエリ名の定義(他と被らない命名規則を持つこと)
qryName = “tmp_Processing_” & Format(Now, “hhnnss”)

‘ SQLの定義(読みやすさを考慮して改行とインデントを徹底する)
sqlText = “SELECT T.CustomerID, Sum(T.Amount) as Total ” & _
“FROM Orders AS T ” & _
“GROUP BY T.CustomerID;”

Set db = CurrentDb

On Error GoTo ErrorHandler

‘ 1. 一時クエリの生成
Set qdf = db.CreateQueryDef(qryName, sqlText)

‘ 2. 処理の実行(例:一時クエリの結果をレコードセットで取得)
‘ ※ここで直接実行するのではなく、必要に応じてクエリを経由させる
Dim rs As DAO.Recordset
Set rs = qdf.OpenRecordset()

‘ ここでrsを使った集計ロジックを回す…

rs.Close
Set rs = Nothing

Cleanup:
‘ 3. 処理後のクリーンアップ(最も重要)
On Error Resume Next
db.QueryDefs.Delete qryName
Set qdf = Nothing
Set db = Nothing
Exit Sub

ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
Resume Cleanup
End Sub

3. 実務で勝つための3つの鉄則

このコードをただコピペするだけでは足りない。現場でトラブルを起こさないために、以下の「アーキテクトの視点」をインストールしてほしい。

① 命名規則による衝突回避

`qryName`を固定値にすると、処理が重なった瞬間に「その名前のクエリは既に存在します」というエラーで落ちる。`Format(Now, “hhnnss”)`や、ユーザー名を含めた動的な命名規則を徹底すること。

② `On Error Resume Next` の正しい使い方

クリーンアップ処理(`Delete`)においてのみ、`On Error Resume Next`を使用する。これは「削除に失敗しても、プログラム全体を停止させない」ための防波堤だ。既に削除済みであればエラーを無視し、処理を完結させるのがベストプラクティスである。

③ データベースの「肥大化」対策

Accessの`.accdb`ファイルは、クエリやテーブルの削除を繰り返すと内部的に断片化(フラグメンテーション)が進む。
一時クエリを多用するシステムであれば、定期的な「最適化(Compact)」を運用フローに組み込むか、あるいは一時テーブル(`TempTables`)をメモリ上の`Recordset`で代替できないか常に検討すること。

最後に:エンジニアとしての矜持

「動けばいい」コードは、半年後の自分を苦しめる。
今回紹介した`CreateQueryDef`による動的生成は、Accessのオブジェクトモデルを正しく理解し、データベースのライフサイクルをコントロールしようという強い意志の表れだ。

道具に使われるな。道具を支配せよ。
このコードをあなたの武器にし、メンテナンスフリーで堅牢なシステムを構築してほしい。

健闘を祈る。

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