【実務・中級編】DAO.QueryDefとADO.Commandの比較:Access内処理と外部DB連携の使い分け基準 – Access VBA解析バイブル

スポンサーリンク

Access開発の分水嶺:DAO.QueryDefとADO.Command、その「使い分け」を極める

Access開発において、クエリ実行の設計はシステムの「背骨」です。適当にSQLを文字列結合して`CurrentDb.Execute`で投げるのは、アマチュアのやり方。バグの温床であり、SQLインジェクションの餌食です。

今日は、プロとして最低限守るべき「DAO.QueryDef」と「ADO.Command」の使い分けの真髄を伝授します。

—

1. 概念の整理:なぜ二つの選択肢があるのか

Access VBAには、歴史的経緯から「DAO」と「ADO」という二つの強力なエンジンが共存しています。

  • DAO (Data Access Objects): Accessのネイティブエンジン(ACE/Jet)。Access内のテーブルやクエリ定義を操作するために生まれてきた「Accessのための専用機」。
  • ADO (ActiveX Data Objects): 汎用的なデータアクセスライブラリ。SQL ServerやOracleといった外部DB、あるいは接続文字列を介した柔軟なデータソースとの対話を得意とする「遠征用兵器」。

結論から言えば、Access内(内部テーブル)の操作にはDAO、外部DB(SQL Server等)との連携にはADOを使うのがエンジニアの鉄則です。

—

2. DAO.QueryDef:Access内処理の絶対王者

Access内部の処理において、`QueryDef`オブジェクトを使わずにSQLを文字列として動的生成するのは「罪」です。

なぜQueryDefなのか?

1. コンパイルの恩恵: クエリ定義として保存することで、Jetエンジンが実行計画を最適化・キャッシュします。
2. パラメータの型安全: パラメータを明示的に定義することで、型の不一致による実行時エラーを未然に防ぎます。
3. セキュリティ: パラメータクエリはSQLインジェクションを物理的に無効化します。

【プロダクションコード】DAO.QueryDefの正しい実装

Public Sub ExecuteParameterizedQuery(ByVal targetID As Long, ByVal status As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef

Set db = CurrentDb
‘ あらかじめクエリ定義を作成しておくか、一時クエリとして生成する
Set qdf = db.QueryDefs(“qry_UpdateStatus”)

‘ パラメータを明示的に指定(文字列結合は絶対禁止)
qdf.Parameters(“pID”) = targetID
qdf.Parameters(“pStatus”) = status

‘ トランザクション制御を忘れずに
db.BeginTrans
On Error GoTo ErrHandler
qdf.Execute dbFailOnError
db.CommitTrans

qdf.Close
Exit Sub

ErrHandler:
db.Rollback
MsgBox “エラー発生: ” & Err.Description
End Sub

—

3. ADO.Command:外部DB連携のスペシャリスト

SQL Server等の外部DBをリンクテーブルとして繋いでいる場合、`DoCmd.RunSQL`やDAOで叩くのは非効率の極みです。ネットワーク越しにテーブル定義を読み込みに行くオーバーヘッドを無視してはいけません。

ADOを使うべき判断基準

  • 接続先がSQL Server / Azure SQL / MySQLであること。
  • ストアドプロシージャを呼び出す必要があること。
  • 非同期処理やタイムアウト制御を細かく制御したいこと。

【プロダクションコード】ADO.Commandの堅牢な設計

Public Sub ExecuteExternalStoredProc(ByVal targetID As Long)
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command

‘ 外部DBへの接続
Set conn = New ADODB.Connection
conn.ConnectionString = “Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=DBName;Integrated Security=SSPI;”
conn.Open

‘ CommandオブジェクトでSQLを構築
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandText = “usp_UpdateData” ‘ ストアドプロシージャ名
.CommandType = adCmdStoredProc

‘ パラメータの型を厳密に定義
.Parameters.Append .CreateParameter(“@ID”, adInteger, adParamInput, , targetID)
.Execute
End With

conn.Close
End Sub

—

4. 現場のリーダーからの一言:設計の優先順位

最後に、エンジニアとしての「眼」を養うための比較表を提示します。

| 観点 | DAO.QueryDef (内部用) | ADO.Command (外部用) |
| :— | :— | :— |
| パフォーマンス | Access内なら最速 | 外部DB接続時の通信負荷に注意 |
| セキュリティ | パラメータクエリで万全 | パラメータ化でSQLインジェクションを防ぐ |
| 実装コスト | 低い(Accessの機能をフル活用) | 高い(接続情報や接続管理が必要) |
| 保守性 | クエリ定義が残るため追跡容易 | コードベースで管理できる |

戒め

「とりあえずSQLを文字列結合して動かした」というコードを見た瞬間、そのプロジェクトの崩壊は始まっています。

  • Access内の処理か、外部の処理か?
  • そのクエリは頻繁に実行されるか?(ならQueryDefのキャッシュが効く)
  • 型変換でエラーが起きる余地はないか?

これらを一つずつ潰していくことこそが、伝説のエンジニアへの第一歩です。自分の書いたコードが、半年後の自分や、後を引き継ぐメンバーを苦しめないようにしてください。コードは「誰かのために」書くものなのです。

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