【入門編】【上級】CurrentDb.QueryDefsのSQLプロパティを動的書き換え:SQLインジェクションを防ぐパラメータ管理 – Access VBA解析バイブル

スポンサーリンク

Access VBAの深淵へ:QueryDefを「正しく」操り、SQLインジェクションを撲滅する

こんにちは。Access開発の世界へようこそ。
もしあなたが今、「クエリのSQLを文字列連結で書き換える」という手法でシステムを組んでいるなら、一度立ち止まってください。それは非常に危険な橋を渡っていることになります。

今日は、Access VBAの真髄である「QueryDef」を正しく扱い、セキュリティと保守性を両立させる「パラメータクエリ」の極意を伝授します。ここをマスターすれば、あなたのコードは一気にプロフェッショナルの領域へと足を踏み入れることになりますよ。

1. なぜ「文字列連結」は悪なのか?

初学者が陥りやすいのが、以下のようなSQL構築です。

‘ 【NG例】絶対にやってはいけない書き方
Dim strSQL As String
strSQL = “SELECT FROM T_受注 WHERE 顧客名 = ‘” & Me.txt顧客名.Value & “‘;”
CurrentDb.QueryDefs(“Q_検索”).SQL = strSQL

一見動くように見えますが、これには致命的な脆弱性「SQLインジェクション」が潜んでいます。もしユーザーが「’ OR ‘1’=’1」のような悪意ある文字列を入力したらどうなるか。クエリは意図しないテーブルを全件表示したり、最悪の場合データを破壊したりします。

また、シングルクォーテーションの処理や日付の書式設定に頭を悩ませる必要もあり、コードはどんどんスパゲッティ化していきます。

2. 解決策:QueryDefの「Parametersコレクション」を使え

Accessの`QueryDef`オブジェクトには、SQLの中に「名前付きパラメータ」を埋め込み、それを安全に管理する仕組みが備わっています。

手順はシンプルです。

1. クエリのデザインビューで、抽出条件に `[P_顧客名]` のように角括弧でパラメータ名を定義する。
2. VBA側で `QueryDef.Parameters` を通じて値をセットする。

これだけで、Accessエンジンが自動的に「安全なデータ」としてクエリに渡してくれるため、インジェクション攻撃は構造的に不可能になります。

3. 実践:安全なクエリ実行コード

では、現場で使える「洗練されたコード」を見てみましょう。

Public Sub RunSecureQuery()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef

‘ データベースオブジェクトを明示的に取得
Set db = CurrentDb

‘ クエリ定義(Q_受注検索)を取得
Set qdf = db.QueryDefs(“Q_受注検索”)

‘ 【重要】パラメータを明示的にセット
‘ ここで値を渡せば、Accessが型変換とエスケープを自動で行う
qdf.Parameters(“P_顧客名”) = Me.txt顧客名.Value
qdf.Parameters(“P_開始日”) = Me.txt開始日.Value

‘ クエリを実行(またはフォームのレコードソースに設定)
‘ 開く場合は OpenRecordset を使うのが定石
Dim rs As DAO.Recordset
Set rs = qdf.OpenRecordset(dbOpenDynaset)

‘ — ここに処理を記述 —

‘ 後始末(オブジェクトの開放)
rs.Close
Set rs = Nothing
Set qdf = Nothing
Set db = Nothing
End Sub

このコードの「賢い」ポイント

  • `CurrentDb`を使い回さない: `Set db = CurrentDb` と変数に格納することで、パフォーマンスを最適化しています。何度も`CurrentDb`を呼び出すのはコストが高いのです。
  • パラメータの型を意識する: `Parameters(“P_顧客名”)` と指定することで、SQLの型に合わせて値が渡されます。日付なら日付として、数値なら数値として正しく扱われます。
  • メモリ管理: `Set = Nothing` で確実にメモリを解放する。これが長期間安定稼働するシステムの秘訣です。

4. 陥りやすいエラーと対策

初心者がよく遭遇する壁は、「パラメータが見つかりません(エラー3265)」というものです。

  • 原因1: クエリのデザインビューで、パラメータを「クエリのパラメータ」として明示していない。
  • 対策:デザインビューのクエリ設定で「パラメータ」ボタンを押し、`[P_顧客名]` と「テキスト型」といった定義を行ってください。
  • 原因2: SQL内のパラメータ名と、VBAで指定した名前の綴りが微妙に違う。
  • 対策:`[P_顧客名]` のように全角・半角や不要なスペースが含まれていないか、徹底的に確認しましょう。

最後に:先輩エンジニアからのエール

「動けばいい」というコードは、数ヶ月後のあなた自身を苦しめます。しかし、このように「パラメータを正しく扱う」という作法を身につければ、セキュリティのリスクを排除し、かつ「なぜそう動くのか」を理解した強いエンジニアになれます。

Access VBAは、正しく使えば非常に強力で安定した武器になります。
まずは今のプロジェクトのクエリを、ひとつずつ「パラメータクエリ」に書き換えてみてください。その小さな一歩が、あなたの開発スキルを確実に一段上のステージへと押し上げます。

もしコードが動かなかったら、まずは落ち着いて「パラメータ名」を見直すこと。それだけで、ほとんどの問題は解決しますよ。

頑張ってください。応援しています!

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