Access VBAの深淵:DAO.QueryDefとADO.Commandの「境界線」を支配せよ
Access開発において、多くのエンジニアが「なんとなく」DAOを使い、SQLが複雑になると「なんとなく」ADOに逃げる。その曖昧な境界線こそが、システムを脆くし、保守性を殺す元凶だ。
今日は、Accessという閉じた世界と、外部DBという広大な世界を繋ぐための「最適解」を授ける。これを読めば、君の書くコードは「動くもの」から「壊れない資産」へと昇華するはずだ。
—
1. 原則:なぜ使い分ける必要があるのか
Access VBAにおけるデータアクセス技術の選定基準は、単純明快だ。「どこにデータがあるか」ではない。「どのエンジンで最適化すべきか」だ。
- DAO (Data Access Objects): Accessのネイティブエンジン(ACE)と心中するための道具。QueryDefという「実行計画のキャッシュ」を操れる唯一の手段。
- ADO (ActiveX Data Objects): 外部DB(SQL Server, Oracle等)や、複雑な非同期処理を行うための汎用ツール。
鉄則: Access内のテーブル操作にADOを使うのは、大砲で蚊を撃つようなものだ。オーバーヘッドが増大するだけで、何一つメリットはない。
—
2. DAO.QueryDef:Access内処理の「真の力」
Access内部でクエリを動かす際、`DoCmd.RunSQL`や文字列結合によるSQL実行を繰り返していないか? それは、毎回家を建てては壊すような非効率な行為だ。
`QueryDef`を使えば、SQLをコンパイル済みの状態で保持できる。パラメータークエリを定義しておけば、実行速度とセキュリティ(SQLインジェクション対策)の両面で最強となる。
実装例:DAOによる堅牢なパラメーター実行
Public Sub ExecuteParamQuery()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
‘ あらかじめ作成済みのクエリ「qry_UpdateStock」を利用
Set qdf = db.QueryDefs(“qry_UpdateStock”)
‘ パラメーターを安全にセット(型安全性を担保)
qdf.Parameters(“prmProductID”) = 101
qdf.Parameters(“prmStockCount”) = 50
‘ トランザクション制御と併用して整合性を守る
db.BeginTrans
On Error GoTo Rollback_Proc
qdf.Execute dbFailOnError
db.CommitTrans
qdf.Close
Set qdf = Nothing
Exit Sub
Rollback_Proc:
db.Rollback
MsgBox “更新失敗: ” & Err.Description, vbCritical
End Sub
—
3. ADO.Command:外部DB連携の「最適解」
外部データベース(SQL Server等)に接続する場合、DAOでは力不足だ。ここで登場するのが `ADODB.Command` である。
なぜ `Recordset` を直接開くのではなく `Command` オブジェクトを使うのか? それは、「SQLをDBサーバー側でプリコンパイルさせる」ためだ。これにより、ネットワーク負荷を抑え、サーバーサイドの実行計画を最大限に活かせる。
実装例:ADOによる外部DBへの安全な接続
Public Sub ExecuteExternalSQL(productID As Long)
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Set conn = New ADODB.Connection
conn.ConnectionString = “Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=DBName;Integrated Security=SSPI;”
conn.Open
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = conn
.CommandType = adCmdText
.CommandText = “UPDATE Products SET Stock = Stock – 1 WHERE ID = ?”
‘ パラメーターの明示的定義(バグの温床を排除)
.Parameters.Append .CreateParameter(“@ID”, adInteger, adParamInput, , productID)
.Execute
End With
conn.Close
Set cmd = Nothing: Set conn = Nothing
End Sub
—
4. 伝説のアーキテクトからのアドバイス
1. 文字列結合によるSQL生成を禁忌とせよ
`”SELECT FROM Table WHERE ID = ” & Me.txtID`。この書き方は、今すぐ捨てろ。パラメータークエリを使えば、データ型が異なることで発生するエラーや、悪意のある入力によるSQLインジェクションを根絶できる。
2. 「閉じる」タイミングの美学
オブジェクトは作成したスコープ内で必ず解放せよ。`Set qdf = Nothing` を怠るエンジニアは、メモリリークという時限爆弾を抱えているのと同じだ。特にDAOの `QueryDef` は、使い終わったら即座に閉じる。これが大規模開発での安定運用の秘訣だ。
3. エラーハンドリングは「逃げ場」ではない
`On Error Resume Next` でエラーを隠蔽するのは、システムの「病巣」を隠す行為に等しい。必ず `dbFailOnError` を使用し、クエリが失敗した際に明確な例外をキャッチできる設計を心がけろ。
—
結論:コードは、意思である
DAOとADO。この二つを使い分けることは、単なる技術的な選択ではない。「どこで処理を完結させ、どこに責任を委ねるか」という設計思想そのものだ。
Accessの内部エンジンを信頼し、DAOで高速化を突き詰める。外部の海に出る時は、ADOで堅牢な橋を架ける。この使い分けをマスターした時、君が書くコードは、誰にも壊されない「本物のシステム」へと進化する。
さあ、エディタを開け。君のコードで、現場の生産性を極限まで引き出せ。
