【入門編】「保存済みクエリ」と「一時クエリ」の使い分け:Accessのファイル肥大化を防ぐメモリ管理戦略 – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。
マクロの記録ボタンを押すだけのステージから抜け出し、「自分の手でシステムをコントロールしたい!」という熱意を持つあなたへ、今日はとても大切で、そして現場のプロほど頭を悩ませる「メモリ管理とクエリのライフサイクル」についてお話しします。

ここをクリアすれば、あなたの作るAccessデータベースは見違えるほど軽くなり、「なんだか最近動きが遅いな……」という謎のファイル肥大化地獄から完全に解放されます。
優しい先輩エンジニアとして、本質をしっかりと、分かりやすく解説していきますね。ここをクリアすれば、Access VBAの基本はバッチリですよ!

—

1. なぜAccessファイルは勝手に太るのか?(真犯人は「保存済みクエリ」)

Accessを使っていると、なんだかデータも入れていないのに `.accdb` ファイルの容量がどんどん膨れ上がっていく現象に出会ったことはありませんか?

「レコードを追加・削除したから?」
もちろんそれもありますが、VBA初学者がやりがちな最大の原因は、「コードの中で作ったクエリを、そのままデータベースに保存し続けていること」にあります。

図解:クエリの居場所と運命

[VBAコード] ──(SQLを発行)──> [Access データベース エンジン]
│
┌─────────────────────────┴─────────────────────────┐
▼ ▼
【保存済みクエリ(永続)】 【一時クエリ(その場限りの使い捨て)】
・ナビゲーションウインドウに残る ・メモリ上だけで実行し、即消去
・ファイルサイズを肥大化させる ・ファイルサイズに影響なし! ★目指すべき姿
・ゴミクエリの温床になる

VBAから `CurrentDb.CreateQueryDef` などの命令を使ってクエリを作ると、それは「デザイン画面で見えるクエリ」としてハードディスクに書き込まれます。これを何千回、何万回とループ処理の中で行うとどうなるでしょう? アクセスの内部システムテーブル(MSysObjectsなど)がゴミデータでパンクし、ファイルが異常肥大化してパフォーマンスが急低下するのです。

—

2. 「保存済みクエリ」と「一時クエリ」の正しい使い分け

では、すべてのクエリを一時的に作ればいいかというと、そうでもありません。適材適所のルールがあります。

  • 保存済みクエリ(永続)を使うべきケース
  • 人間がフォームやレポートのレコードソースとして直接指定するもの。
  • 複雑な結合(JOIN)や集計があり、あらかじめ設計図として固定しておきたいもの。
  • 一時クエリ(動的SQL・その場限りの実行)を使うべきケース
  • ボタンを押したときの処理(イベントプロシージャ)の中で、条件が毎回変わるSQLを実行してデータを更新・追加・削除するもの。
  • ループ処理の中で条件を変えて何度も実行するような処理。

今回のテーマは、後者の「一時クエリをスマートに使い捨て、ファイルを肥大化させないメモリ管理戦略」です。

—

3. 実践!ファイルを汚さない「一時クエリ」のVBAコード

それでは、実務でそのまま使えるコードを見ていきましょう。
今回は、「画面に入力された条件(顧客ID)に基づいて、売上データを一括更新する」というシナリオを想定します。

ここに、ファイル肥大化を防ぐための極意(プロの技)が詰まっています。

Sub UpdateCustomerStatus()
‘ =====================================================================
‘ テーマ:一時クエリ(QueryDef)のライフサイクル管理とメモリ解放
‘ 解説:ファイルに保存せず、メモリ上で瞬時に実行して跡形もなく消去する
‘ =================>====================================================

Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strSQL As String

On Error GoTo ErrorHandler

‘ 1. 現在のデータベースオブジェクトを取得
Set db = CurrentDb

‘ 2. 実行するSQL文を組み立てる(動的SQL)
‘ ※ここでは名前のない(””)一時クエリとして定義します
strSQL = “UPDATE T_Sales SET Status = ‘完了’ WHERE CustomerID = 999;”

‘ 3. 【核心】名前を付けずにQueryDefを作成(=ファイルに保存されない!)
‘ 引数を省略、または “” を渡すことで、メモリ上だけに存在させる
Set qdf = db.CreateQueryDef(“”, strSQL)

‘ 4. クエリの実行
qdf.Execute dbFailOnError

MsgBox “データの更新が正常に完了しました。”, vbInformation, “処理成功”

CleanUp:
‘ 5. 【重要】オブジェクトの明示的なメモリ解放
‘ VBAでは、使ったメモリは自分で片付けるのがプロの流儀です
If Not qdf Is Nothing Then
qdf.Close
Set qdf = Nothing
End If

If Not db Is Nothing Then
Set db = Nothing
End If

Exit Sub

ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “異常終了”
Resume CleanUp
End Sub

コードのここがスゴイ!3つのポイント

1. `db.CreateQueryDef(“”, strSQL)` の空文字(””)
第一引数に名前を渡さず、空の文字列を指定することがポイントです。これによってAccessは「あ、これ保存しなくていいやつね」と判断し、ハードディスクを汚さず、メモリ(RAM)上だけでクエリを構築します。
2. `qdf.Execute dbFailOnError`
SQLを実行するときは、`DoCmd.RunSQL` よりも `QueryDef.Execute` を使ってください。エラー時に自動でロールバック(変更をなかったことにする)をかけやすくなり、警告メッセージの表示・非表示もコントロールしやすくなります。
3. 徹底的なメモリ解放(CleanUpラベル)
VBAのオブジェクト変数(`db` や `qdf`)は、処理が終わってもすぐにはメモリから消えてくれないことがあります(ガベージコレクションのタイムラグ)。`Set qdf = Nothing` と明示的に解放し、ファイル肥大化だけでなくメモリリークも完全に防ぎます。

—

4. ありがちな失敗と陥りやすいトラップ

初学者の頃によやりがちな、典型的なアンチパターンをご紹介します。

❌ やってはいけない書き方

‘ 【絶対NG】ループ内で名前付きクエリを作り続ける地獄のコード
Dim i As Long
For i = 1 to 1000
‘毎回 “TempQuery” という名前で保存してしまう!
‘ -> アクセスのシステムテーブルが1000個のゴミクエリでパンクします
CurrentDb.CreateQueryDef “TempQuery” & i, “SELECT FROM T_Master WHERE ID = ” & i
Next i

このコードを動かすと、ナビゲーションウインドウには見えないものの、内部的には1,000個ものクエリ定義がデータベースファイルに刻み込まれ、ファイルサイズがみるみる跳ね上がります。もしこのようなコードを見かけたら、即座に今回紹介した「名前なし(`””`)のQueryDef」に書き換えてください。

—

まとめ

いかがでしたでしょうか?

  • 保存済みクエリは、UIやレポートの「設計図」として大切に扱う。
  • 一時クエリは、名前を付けずに `CreateQueryDef(“”, sql)` でメモリ上に生成し、使い終わったら即座に `Close` & `Nothing` で捨てる。

このライフサイクル管理を意識するだけで、あなたのAccessアプリケーションは見違えるほど軽快になり、長期間運用してもファイルが肥大化しなくなります。

「コードを書くだけでなく、メモリやストレージの寿命まで気遣う」。ここまでできれば、あなたはもう立派なプロフェッショナルな業務自動化エンジニアです。

自信を持って、明日からの開発にこの知見を活かしてくださいね!

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