Access VBAの深淵へ:動的SQLで「ワイルドカード」の罠を華麗に回避する技術
こんにちは。Accessという広大な海を渡る皆さんの航海を支える、チーフアーキテクトです。
Access VBAで「検索機能」を作ろうとしたとき、誰もが一度はぶつかる壁があります。それが「ワイルドカードの表記ゆれ」です。
「あれ?さっきまで動いていたSQLが、SQL Serverに接続した途端に結果が空っぽになったぞ?」
そんな経験はありませんか?実はこれ、Access(Jet/ACEエンジン)とSQL Serverの「言語の訛り」の違いが原因なのです。今日は、この罠をスマートに回避し、どんな環境でも揺るがない「最強の動的SQL生成術」を伝授しましょう。
—
1. なぜワイルドカードが「環境」で変わるのか?
Access VBAでSQLを書くとき、私たちは大きく分けて2つのエンジンを使い分けます。
1. DAO(Data Access Objects): Access標準のエンジン。`LIKE “A”` と書く。
2. ADO(ActiveX Data Objects): SQL Serverなど外部DBと通信する際に使う。`LIKE “A%”` と書く。
この「“(アスタリスク)」と「`%`(パーセント)」の決定的な違い。これを意識せずにコードを書くと、開発環境では動くのに、本番環境で急にエラーを吐くという「悪夢のバグ」に繋がります。
比較表:ワイルドカードの作法
| 検索対象 | Access (DAO/Jet) | SQL Server (ADO/T-SQL) |
| :— | :— | :— |
| 「あ」から始まる | `LIKE “あ”` | `LIKE “あ%”` |
| 任意の1文字 | `LIKE “あ?”` | `LIKE “あ_”` |
—
2. 賢いエンジニアの回答:ラッパー関数で「吸収」する
いちいちSQLを書くたびにif文で分岐させていたら、コードが汚れ、保守性が死にます。ここは「環境に応じてワイルドカードを変換するラッパー関数」を一つ用意して、SQL生成の工程を自動化しましょう。
以下のコードは、あなたの「武器」となる関数です。モジュールにコピペして、いつでも呼び出せるようにしておいてください。
‘ @brief SQLの検索条件用ワイルドカードを、接続先エンジンに合わせて変換する
‘ @param strTarget 検索するキーワード
‘ @param isServerSide SQL Server等へのクエリであればTrue
‘ @return 変換済みの文字列
Public Function FormatLikeCondition(ByVal strTarget As String, Optional ByVal isServerSide As Boolean = False) As String
Dim s As String
s = strTarget
If isServerSide Then
‘ SQL Server用: を % に、 ? を _ に置換
s = Replace(s, “”, “%”)
s = Replace(s, “?”, “_”)
Else
‘ Access標準: % を に、 _ を ? に置換
s = Replace(s, “%”, “”)
s = Replace(s, “_”, “?”)
End If
FormatLikeCondition = s
End Function
—
3. 実践:動的SQL生成の作法(QueryDefの活用)
単に文字列を連結するだけのSQLは、セキュリティの観点(SQLインジェクション)からも推奨されません。`QueryDef` オブジェクトを使い、パラメータを安全に渡すのがプロの流儀です。
Public Sub RunDynamicSearch(ByVal keyword As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
‘ 既存のクエリ定義を再利用(なければ作成)
Set qdf = db.QueryDefs(“qry_DynamicSearch”)
‘ ラッパー関数でワイルドカードを適切に変換してからパラメータにセット
‘ 今回はAccessエンジン前提なのでisServerSideはFalse
qdf.Parameters(“prmKeyword”) = FormatLikeCondition(keyword, False)
‘ ここでクエリを実行、またはフォームのレコードソースに設定
‘ DoCmd.OpenQuery “qry_DynamicSearch”
Set qdf = Nothing
Set db = Nothing
End Sub
陥りやすいエラー:ここだけは注意!
- パラメータの型不一致: `FormatLikeCondition` で変換した結果が正しい型(文字列)になっているか確認してください。
- クエリ定義の保存: `QueryDef` は一度作成するとDB内に残ります。一時的な処理であれば、最後に `db.QueryDefs.Delete` で消去するか、`Temporary` なプロパティを活用しましょう。
—
最後に:なぜ「ここ」をクリアすべきなのか
プログラミングにおける「自動化」とは、単にコードを書くことではありません。「環境の差異を意識させない隠蔽(カプセル化)」をいかにスマートに行うか、に尽きます。
今日紹介したワイルドカードの変換手法は、小さなテクニックに見えるかもしれません。しかし、こうした細かな「揺らぎ」をすべて吸収する設計を積み重ねることで、あなたのAccessシステムは、1年後も、10年後も、誰がメンテナンスしても壊れない「堅牢な資産」へと進化します。
「ここをクリアすれば、Access VBAの基本はバッチリですよ」。
迷ったらまたいつでも戻ってきてください。あなたのエンジニアリングライフが、より快適で創造的であるよう願っています。
