Access VBAの深淵へ:QueryDefで「爆速」SQLを操る極意
こんにちは。Accessの迷宮に迷い込み、クエリの遅さに頭を抱えている皆さんに、少しだけ深い話をしましょう。
多くの方が「マクロの記録」や「クエリデザイナー」の延長でSQLを書きますが、大規模なデータセットを扱うとき、そのアプローチは「真っ暗闇で全力疾走する」ようなものです。
今日は、Accessの心臓部である`QueryDef`オブジェクトを使いこなし、データベースが「あ、このデータならここにあるな」と最短距離で探しに行ける(=インデックスを最大限に活かす)SQLの書き方を伝授します。
—
1. なぜ「QueryDef」を使うべきなのか?
VBAでSQLを動かす際、`DoCmd.RunSQL`や`CurrentDb.Execute`に文字列を直書きしていませんか?
‘ 悪い例:毎回SQLを解釈させる
CurrentDb.Execute “DELETE FROM T_Sales WHERE SalesDate < #" & Date - 30 & "#"
これでは、Accessは毎回「このSQLは何をしたいんだ?」とゼロから解析(実行計画の作成)を始めます。対して`QueryDef`は、クエリを事前に定義して保存するため、実行計画が最適化された状態で保持されます。これが、プロの現場で`QueryDef`が愛される理由です。
—
2. インデックスが「泣く」クエリ、笑うクエリ
インデックスは「図書館の索引」です。索引を無視した検索は、全ページをめくることに等しい。以下のSQLを見てください。
悲劇的なSQL(インデックスが効かない)
SELECT FROM T_Sales WHERE Year(SalesDate) = 2023;
なぜダメなのか?
`Year()`関数でデータを加工してしまうと、Accessは「全てのレコードの日付を分解して確認」しなければなりません。インデックスは「値そのもの」を指しているため、関数を通すとその恩恵を捨ててしまうのです。
プロのSQL(インデックスを活かす)
SELECT FROM T_Sales WHERE SalesDate BETWEEN #2023/01/01# AND #2023/12/31#;
なぜ良いのか?
「値そのもの」で範囲指定することで、Accessはインデックスの木構造を辿り、該当箇所にピンポイントで到達できます。これが数万レコードの壁を超えるための鉄則です。
—
3. 実践:動的パラメータークエリで最適化する
では、VBAから`QueryDef`を使って、安全かつ高速にクエリを操作するテンプレートを共有します。
Public Sub RefreshSalesQuery(startDate As Date, endDate As Date)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
‘ 既存のクエリ定義を取得(なければ作成する設計も可)
Set qdf = db.QueryDefs(“Q_Sales_Dynamic”)
‘ パラメーターに値を渡す
‘ 直接SQLを書き換えるのではなく、定義済みのパラメーターを差し替える
qdf.Parameters(“[prmStart]”) = startDate
qdf.Parameters(“[prmEnd]”) = endDate
‘ 実行計画を維持したまま、引数だけを入れ替えて実行
qdf.Execute dbFailOnError
Set qdf = Nothing
Set db = Nothing
End Sub
このコードのポイント
1. `dbFailOnError`: エラー発生時にトランザクションを自動ロールバックしてくれます。データの整合性を守るための必須オプションです。
2. `Parameters`コレクション: SQL文字列を「連結」すると、SQLインジェクションのリスクが高まり、かつ実行計画が再計算されてしまいます。パラメーターを使うことで、安全かつ高速に実行できます。
—
4. プロの視点:陥りやすい罠
最後に、初心者がやりがちな「パフォーマンスの罠」を二つだけ。
- `SELECT ` の呪縛: 必要な列だけを指定してください。不要な列を読み込むことは、メモリとI/Oを無駄に食いつぶす行為です。
- 「とりあえず全件取得」の誘惑: `DLookup`や`DCount`をループの中で使っていませんか? それはデータベースに対して「毎回玄関まで迎えに来い」と命令しているようなもの。`QueryDef`で一括処理させるのが、Access高速化の王道です。
—
まとめ:Accessを「ただの箱」にしないために
Access VBAを掌握するということは、「データベースエンジンの考え方」に歩み寄るということです。
1. 関数で加工せず、値そのもので検索する
2. `QueryDef`を使い、実行計画を固定する
3. `Parameters`を使い、SQLの安全と再利用性を担保する
これらを意識するだけで、あなたの書くコードは「動くもの」から「速く、堅牢なシステム」へと進化します。
「ここをクリアすれば、Access VBAの基本はバッチリですよ」。
次に書くクエリでは、ぜひ「データベースがどうやってデータを探しに行くか」を想像してみてください。その視点こそが、伝説のエンジニアへの第一歩です。
