こんにちは!Access VBAの世界へようこそ。
マクロの記録ボタンを押すだけの世界から一歩踏み出し、「自分の手でシステムをコントロールしたい」と願うあなたへ、今日はとてもエキサイティングで実用的なお話をしますね。
今回テーマにするのは、Access VBAの心臓部とも言える「DAOのQueryDef(クエリ定義)」と「ADO」の使い分けです。
「SQLって何?」「DAOとかADOとか、なんだか難しそう……」と思ったそこのあなた、大丈夫ですよ。ここをクリアすれば、あなたはもう「ただのAccess利用者」ではなく、「データベースを自在に操るエンジニア」の仲間入りです。
優しく、そして本質的なところまで丁寧に紐解いていきますので、ぜひ最後までついてきてくださいね!
—
1. そもそも「QueryDef(クエリ定義)」ってなに?
Accessの画面(ナビゲーションウインドウ)で、「クエリ」を作ったことはありますか?
テーブルからデータを絞り込んだり、結合したりする、あの保存されたSQLの塊のことです。
VBAの世界では、この「保存されたクエリ」をプログラムから自由自在に操作するための仕組みをQueryDef(クエリディフ)と呼びます。
イメージ図:QueryDefの立ち位置
[ あなたのVBAコード ]
↓ (指示)
[ QueryDef (クエリ定義) ] ──→ Access内部のエンジンが「超高速」で実行!
↓
[ Accessの内部テーブル ]
QueryDefの最大の武器は、「Accessのエンジン(Jet / ACE)に事前に計画を立てさせ、最適化された状態で実行できる」という点にあります。
—
2. 【基本】QueryDefが適しているケース(真骨頂)
Accessの「内部テーブル(今あなたが作っているAccessファイル内にあるテーブル)」を相手にする場合、主役は間違いなくDAO(Data Access Objects)であり、QueryDefです。
特に、以下のようなケースではQueryDefを使わない手はありません。
- パラメータ付きの集計や更新を、安全かつ爆速で行いたいとき
- Accessのクエリデザイナで作った複雑なSQLを、VBAから使い回したいとき
実践コード:QueryDefを使った安全なパラメータクエリ
「ユーザーが入力した条件に一致するデータを抽出したい」というよくある要件で見てみましょう。文字列をそのままSQLにくっつけると「SQLインジェクション」や「シングルクォーテーションの書き忘れエラー」の温床になりますが、QueryDefなら完璧に解決できます。
Sub UpdateStatusByQueryDef()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
‘ 現在のデータベース(自分自身)を参照
Set db = CurrentDb
On Error GoTo ErrorHandler
‘ 1. あらかじめ作っておいたクエリ定義を取得する
‘ (※「qryUpdateStatus」という名前のパラメータクエリが事前にある想定)
Set qdf = db.QueryDefs(“qryUpdateStatus”)
‘ 2. パラメータに値を安全にバインド(代入)する
qdf.Parameters(“prmStatus”) = “完了”
qdf.Parameters(“prmDate”) = #2023/12/31#
‘ 3. クエリを実行(更新系クエリの場合)
qdf.Execute dbFailOnError
MsgBox “データの更新が完了しました!”, vbInformation, “成功”
ErrorHandler:
If Err.Number <> 0 Then
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
End If
‘ オブジェクトの解放(メモリリークを防ぐプロの作法)
Set qdf = Nothing
Set db = Nothing
End Sub
ここがポイント!
`dbFailOnError`というおまじない(オプション)をつけておくことで、途中でエラーが起きたときにデータベースの変更が自動でロールバック(なかったことに)されます。これがDAOの優しさであり、強みです。
—
3. 【転換点】では、QueryDefが「適していない」ケースとは?
では、なんでもかんでもQueryDefを使えばいいのでしょうか?
実は、Accessの守備範囲を超えた瞬間、QueryDefは牙を抜かれます。
次のようなケースでは、QueryDef(およびDAO)ではなく、ADO(ActiveX Data Objects)の出番になります。
1. 外部のデータベース(SQL Server、MySQL、Oracleなど)と直結して、非同期処理や高度な接続制御をしたいとき
2. Accessファイルを保存せず、完全にメモリ上(Recordset)だけでSQLを動的に組み立てて完結させたいとき
3. そもそもAccessの「クエリ定義」として永続的に保存する必要がない、その場限りの使い捨て動的SQLを投げたいとき
QueryDefはあくまで「Accessの中にクエリを定義(保存)する」仕組みです。ですから、サーバー側へ直接重い処理を投げたり、一時的なSQLを何万回も動的に生成して捨てるような場面では、コードが汚れたりパフォーマンスが落ちたりします。
—
4. DAOとADOの使い分け:アーキテクチャ設計の基準
ここで、実務で迷わないための「黄金の判断基準」を授けましょう。
| 比較項目 | DAO (QueryDef中心) | ADO |
| :— | :— | :— |
| 得意な相手 | Access内部テーブル | 外部データベース(SQL Server等) |
| 保存の有無 | クエリとしてファイル内に保存される | コード内で完結し、保存されない |
| 速度(内部) | 爆速(Accessエンジンに最適化される) | 少しオーバーヘッドがある |
| 柔軟性 | 構造化されたクエリ向き | 動的なSQL構築・外部連携向き |
- 結論:
- Accessのローカル開発なら、基本はDAO(QueryDef)で組み立てるのが最も安定し、パフォーマンスも出ます。
- 大規模なクライアント・サーバーシステム(UPSIZEした環境)や、他 시스템との連携が絡むなら、ADOへと視点を切り替えます。
—
5. 初学者が陥りがちな罠とエラー回避の極意
最後に、現場でよくある「やっちまった!」を防ぐための知見をシェアします。
罠1:QueryDefを毎回「新規作成」してゴミ屋敷にする
VBAから `db.CreateQueryDef` を使って、実行のたびに新しいクエリを作っては捨てているコードを見かけます。これはAccessのファイルサイズ(内部のシステムテーブル)を無駄に肥大化させ、動作を重くする原因(データベースの破損リスクも!)になります。
- 対策: 基本はクエリデザイナであらかじめ名前付きのクエリを作っておき、VBAからはそれを「呼び出してパラメータを渡すだけ」にしましょう。
罠2:オブジェクトの解放忘れ
先ほどのサンプルコードの最後に、`Set qdf = Nothing` と書いたのを覚えていますか?
VBAでは、オブジェクト変数に `Nothing` を入れてメモリを明示的に解放してあげることが、安定稼働するシステムの秘訣です。これをサボると、見えないところでメモリを食いつぶし、突然Accessがフリーズする原因になります。
—
まとめ
いかがでしたでしょうか?
- Access内の処理なら、DAOのQueryDefを頼るのが一番の近道で安全。
- 外部データベースやその場限りの動的SQLなら、ADOにバトンタッチ。
この使い分けの軸が頭に入った瞬間から、あなたの書くAccess VBAのコードは、プロのアーキテクチャへと昇華します。
ここをクリアすれば、もうAccess VBAの基本はバッチリです!
ぜひ、今日のコードをご自身の開発環境で試してみてくださいね。あなたのAccess開発ライフがより快適なものになるよう、応援しています!
