【実務・中級編】ワイルドカード検索を安全に実装する:LIKE演算子とパラメータクエリの融合 – Access VBA解析バイブル

スポンサーリンク

Access VBAの「暗黒面」を断つ:動的SQLとワイルドカードの正しい作法

現場でよく見る「動的SQLの文字列結合」という名の爆弾。
`strSQL = “SELECT FROM T_Master WHERE Name LIKE ‘” & Me.txtSearch.Value & “‘”`
初心者が通る道とはいえ、この書き方は「バグの温床」かつ「セキュリティリスクの塊」です。

なぜこれがダメなのか。単にインジェクションのリスクだけではありません。
`’`(シングルクォート)が含まれた文字列が入力された瞬間にクエリは構文エラーで沈没し、運用保守のコストを跳ね上げます。

今日は、Access VBAで「堅牢かつ高速」な検索機能を実装するための、プロフェッショナルな解法を伝授します。

—

1. なぜ「文字列結合」を捨て、「Parameters」を使うべきか

Accessの `QueryDef` オブジェクトと `Parameters` コレクションを活用すれば、SQLの構文解析とデータのバインドを分離できます。

  • 型安全: データ型を明示することで、予期せぬ型変換によるエラーを防ぐ。
  • エスケープ不要: ユーザー入力内の特殊文字をSQL構文の一部として誤解させない。
  • プランキャッシュの再利用: クエリの実行計画が固定されるため、大規模データではパフォーマンスが安定する。

—

2. 実装の極意:LIKE演算子とパラメータの融合

多くのエンジニアが躓くのが「パラメータにワイルドカードを含めるとうまく動かない」という点です。
SQL内で `LIKE ?` と書き、パラメータに `keyword` を渡しても、AccessのJET/ACEエンジンはこれを「リテラル(文字列そのもの)」として扱ってしまい、結果がゼロになります。

正解は、SQL側で `Like “” & [prm] & “”` と記述し、パラメータには純粋な検索ワードのみを渡すことです。

—

3. プロダクションコード:保守可能な検索実装

このコードは、エラーハンドリングを備え、再利用性を考慮した設計です。フォームの検索ボタン等に配置してください。

Public Sub ExecuteSecureSearch(ByVal keyword As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rs As DAO.Recordset

On Error GoTo ErrorHandler

Set db = CurrentDb
‘ 既存のクエリ定義を再利用(または一時クエリを作成)
Set qdf = db.QueryDefs(“qry_MainSearch”)

‘ パラメータに値をセット(ワイルドカードはSQL側で処理する)
‘ SQL例: SELECT FROM T_Clients WHERE ClientName Like “” & [prmKeyword] & “”
qdf.Parameters(“prmKeyword”) = keyword

‘ レコードセットの取得
Set rs = qdf.OpenRecordset(dbOpenSnapshot)

‘ ここでフォームのレコードソースにセットするなどの処理を行う
‘ Set Me.Recordset = rs

Debug.Print “検索完了: ” & rs.RecordCount & ” 件ヒットしました。”

CleanUp:
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set qdf = Nothing
Set db = Nothing
Exit Sub

ErrorHandler:
MsgBox “検索中にエラーが発生しました: ” & Err.Description, vbCritical
Resume CleanUp
End Sub

このコードが「現場で勝てる」理由

1. DAOの明示的な解放: `Set qdf = Nothing` を徹底することで、メモリリークを確実に防ぎます。
2. `dbOpenSnapshot` の利用: 検索結果を編集しないのであれば、スナップショットを使うべきです。これは読み取り専用でオーバーヘッドが最小限に抑えられます。
3. 分離設計: SQLのロジックはクエリデザインウィンドウ(または定義文)に隠蔽し、VBA側はパラメータを流し込む「パイプ」に徹する。これが長期保守の鉄則です。

—

4. 運用時の注意点:クエリの生存期間

「動的SQLを生成して `QueryDef` を作成・削除する」という手法を好む人もいますが、私は推奨しません。
Accessの内部メタデータが断片化し、DBファイルが肥大化する原因になります。

  • 推奨: あらかじめ名前付きクエリを作成しておき、`Parameters` を書き換える。
  • 例外: 検索条件が動的に大幅に変化する場合のみ、`db.CreateQueryDef(“”, strSQL)` を使った一時クエリを作成すること。

まとめ

プロフェッショナルは「動くコード」ではなく「壊れないコード」を書きます。
`LIKE` 演算子とパラメータクエリを正しく組み合わせることで、あなたのAccessアプリは、ユーザーがどんな過激な文字列を検索窓に打ち込んでも、決して悲鳴を上げることはありません。

まずは、あなたの既存の検索ロジックを、この「パラメータバインド方式」へ書き換えてみてください。それだけで、コードの品格と安定性が一段上のステージへ昇華するはずです。

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