Access VBAの「動的SQL」に潜む地雷を排除する:QueryDefバリデーターの極意
Access開発の現場で、`QueryDef`を動的に書き換えて運用しているエンジニアは多いだろう。しかし、その実装が「実行時エラーが発生するまでバグに気づけない」という脆弱性を孕んでいるとしたら、それはエンジニアとしてあまりに無防備だ。
SQLを文字列として結合し、それを`QueryDef`に流し込む。一見簡単そうに見えるが、タイポ、クォーテーションの閉じ忘れ、予約語の競合など、動的SQLには常に「未知の爆弾」が隠されている。
今回は、伝説的アーキテクトの視点から、「実行前にSQLの正当性を証明するバリデーター」の実装指針を授ける。
—
1. なぜ「実行時エラー」に頼ってはいけないのか
初心者はコードを書き、実行し、エラーが出たら修正する。このサイクルを繰り返す。だが、業務システムにおいて「エラーが発生して初めて問題が判明する」という状態は、運用リスクの塊だ。
特に`QueryDef`の`.SQL`プロパティを書き換える場合、Accessは「定義を更新した瞬間」ではなく「クエリを実行した瞬間」に初めて構文解析を行う。つまり、エラーが発覚するのが、ユーザーがボタンを押したその瞬間である可能性が高い。
これを防ぐには、「定義を確定させる前に、Accessのエンジンに構文チェックを代行させる」というプロキシ(代理)戦略が必要になる。
—
2. 「一時クエリ」を活用した構文チェックの設計
SQLが正しいかどうかを判断する唯一の正当な審判は、Accessのクエリエンジンだ。本番の`QueryDef`を汚さず、かつ正確にチェックするには、「チェック専用の使い捨てQueryDef」を生成し、そこにSQLを流し込んで例外をキャッチするのが最も堅牢だ。
実装コード:SQLバリデーター
この関数は、SQLを引数に受け取り、それが構文的に正しいか否かをブール値で返す。
‘ @description SQL構文の妥当性を検証するバリデーター
‘ @param strSQL 検証対象のSQL文字列
‘ @return 構文が正しければTrue、エラーがあればFalse
Public Function ValidateSQL(ByVal strSQL As String) As Boolean
Dim db As DAO.Database
Dim qdfTemp As DAO.QueryDef
Set db = CurrentDb
‘ 構文チェック用のダミー名を設定
Const TEMP_QDF = “tmp_Validation_Check”
On Error Resume Next
‘ 既存のダミーがあれば削除
DoCmd.DeleteObject acQuery, TEMP_QDF
On Error GoTo 0
On Error GoTo ErrorHandler
‘ 一時的なQueryDefを作成し、SQLをセット
‘ ここでSQLの構文解析がトリガーされる
Set qdfTemp = db.CreateQueryDef(TEMP_QDF, strSQL)
‘ 成功すればTrue
ValidateSQL = True
Cleanup:
On Error Resume Next
qdfTemp.Close
DoCmd.DeleteObject acQuery, TEMP_QDF
Set qdfTemp = Nothing
Exit Function
ErrorHandler:
‘ 構文エラー時はここに飛ぶ
Debug.Print “SQL構文エラー検出: ” & Err.Description
ValidateSQL = False
Resume Cleanup
End Function
—
3. 実務で「負けない」ための3つの鉄則
このバリデーターを導入するだけではまだ甘い。真のプロフェッショナルは、以下の3点を意識してSQLを構築する。
① 文字列連結の「クリーンルーム」を用意する
SQL構築時に、`”SELECT FROM Table WHERE ID = ” & Me.txtID` のような直書きは避けるべきだ。SQL構築専用のクラスを作成し、そこですべてのエスケープ処理とバリデーションを完結させる設計にせよ。
② パラメータークエリへの回帰
可能な限り動的SQLを避け、`PARAMETERS`句を使用した固定クエリをベースにし、`QueryDef.Parameters`コレクション経由で値を渡せ。これが「SQLインジェクション」と「構文エラー」の両方を防ぐ最もエレガントな解法だ。
③ トランザクションと分離
動的SQLを実行する際は、必ず`DAO.Database`のトランザクション制御、あるいは排他制御を考慮せよ。バリデーションを通ったSQLであっても、テーブルのロックや接続状態によって実行時エラーは起こりうる。
—
結論:技術は「守り」から固める
「動的にSQLを組み立てる」という行為は強力だが、同時に最もバグを生みやすい。今回紹介したバリデーターは、単なるエラーチェックではなく、「開発者の無意識なタイポを、実行前に矯正する仕組み」である。
業務システムで最も高価なのは、デバッグにかかる時間ではなく、ユーザーの信頼を損なう停止時間だ。
コードを書く前に、まず「どうすればエラーを未然に検知できるか」を自問せよ。それが、君が伝説的なエンジニアへと歩むための最初の一歩だ。
さあ、コードを改善しよう。君のシステムは、もっと堅牢になれる。
