【Access VBA】QueryDefの闇を断つ:SQLにフォームを直書きするな
Access開発の現場で、初心者が最初に突き当たる壁であり、同時に「負債」の入り口となるのが「SQL文の中に直接 `Forms!フォーム名!コントロール名` を埋め込む」という悪習だ。
一見、手軽で便利に見えるこの手法。しかし、これは業務システムを構築するプロフェッショナルの視点から言わせれば、「保守性を自ら放棄する自殺行為」に他ならない。なぜこれがいけないのか、そしてどう設計すべきか。本質を突こう。
—
なぜ `Forms!…` をSQLに直書きしてはいけないのか
SQL文の中に直接コントロール名を書くと、以下のような致命的な問題が発生する。
1. 依存関係の硬直化: フォームの名前やコントロール名を変更した瞬間にSQLが沈黙し、デバッグの難易度が跳ね上がる。
2. 型変換の暗黙的リスク: Accessエンジンがフォーム上の値を解釈する際、意図しない型変換(日付の誤解釈やNullの扱い)が起きる。
3. 再利用性の欠如: そのSQLは「特定のフォームが開いている時」しか動かない呪いにかかる。バックグラウンド処理や別モジュールからの呼び出しが不可能になる。
真のエンジニアは、「SQL定義(QueryDef)」と「ユーザーインターフェース(Form)」の間に明確な境界線(インターフェース)を引く。 これが堅牢なシステムを作る鉄則だ。
—
解決策:変数を経由した「パラメータの明示的注入」
QueryDefの `Parameters` コレクションを活用せよ。これこそが、Accessが持つ強力な機能であり、かつ安全にSQLを動的に制御するための「正攻法」である。
実践的なプロダクションコード
以下のコードは、フォーム上の値を安全にクエリへ引き渡し、実行するテンプレートだ。これをモジュールに実装すれば、複雑なSQLもクリーンに管理できる。
‘ ———————————————————
‘ 機能: パラメータクエリを動的に実行する汎用プロシージャ
‘ ———————————————————
Public Sub ExecuteParametricQuery(ByVal queryName As String, ByVal targetDate As Date, ByVal empId As Long)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
Set qdf = db.QueryDefs(queryName)
‘ SQL内のパラメータを明示的にセットする
‘ これにより、SQL側で型が厳密に評価される
With qdf
.Parameters(“[prm_Date]”) = targetDate
.Parameters(“[prm_EmpID]”) = empId
‘ 実行する(アクションクエリの場合)
.Execute dbFailOnError
‘ 終了処理
.Close
End With
Set qdf = Nothing
Set db = Nothing
End Sub
SQL側の記述(クエリ定義のSQL)
PARAMETERS [prm_Date] DateTime, [prm_EmpID] Long;
SELECT FROM T_勤怠ログ
WHERE 勤務日 = [prm_Date] AND 社員ID = [prm_EmpID];
—
プロフェッショナルの設計思想:3つのポイント
1. SQLの自己完結性を保つ
`PARAMETERS` 句を必ず記述すること。これにより、クエリ単体で実行しようとした際にもAccessが「何を入力すべきか」を判断できる。これは開発中の単体テストにおいて劇的な効率向上をもたらす。
2. Null対策の徹底
フォーム上のコントロールが空(Null)の可能性がある場合、変数へ格納する段階で `Nz()` 関数や型判定を行うこと。「SQLが動かない」原因の8割は、予期せぬNullによる型不一致だ。
3. DAOのライフサイクルを管理する
`QueryDef` オブジェクトは、開きっぱなしにするとメモリリークの原因となる。`dbFailOnError` を指定して、エラー発生時に確実にトランザクションがロールバックされるよう設計し、最後に必ず `.Close` を呼ぶこと。
—
結論:コードは「疎結合」に、心は「堅牢」に
フォームのコントロール名をSQLに埋め込むのは、いわば「家の中に直接配線を通す」ようなものだ。リフォーム(修正)のたびに壁を壊すことになる。
変数経由でパラメータを渡す手法は、一見手間がかかるように見えるかもしれない。しかし、「どこでエラーが起きても原因が即座に特定できる」という安心感は、長期間運用する業務システムにおいて何よりも勝る資産となる。
明日からの開発では、ぜひこの「インターフェース分離」を意識してほしい。あなたの書くコードが、誰にとっても読みやすく、何年経っても壊れない「資産」になることを願っている。
