【入門編】動的SQL生成における「ワイルドカード(* / %)」の使い分け:DAOとADOの仕様差を吸収する – Access VBA解析バイブル

スポンサーリンク

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の基本はバッチリですよ」。
迷ったらまたいつでも戻ってきてください。あなたのエンジニアリングライフが、より快適で創造的であるよう願っています。

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