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

スポンサーリンク

Access VBAを掌握する:動的SQLの「ワイルドカード地獄」を完全制圧するアーキテクチャ

業務システムの開発において、最も生産性を低下させ、バグの温床となるのが「環境依存のゆらぎ」だ。特にAccess(ACEエンジン)のローカルテーブルと、バックエンドのSQL Server(T-SQL)を共存させている現場では、ワイルドカードの扱いで頭を抱えるエンジニアが後を絶たない。

「Accessでは “ なのに、SQL Serverでは `%` に書き換えないと動かない」

この事実に気づかず、文字列置換を場当たり的に書いているなら、今すぐその手を止めてほしい。保守性の低いスパゲッティコードを生み出すのはもう終わりにしよう。今回は、この差異をエンジンレベルで吸収し、堅牢な動的SQLを生成するための「真の設計論」を伝授する。

—

1. なぜ「その場しのぎの置換」が滅びを招くのか

多くの初心者が陥る罠は、SQL組み立ての段階で `Replace(str, “”, “%”)` を叩き込む手法だ。これは以下の理由で致命的な欠陥を抱える。

  • エスケープシーケンスの破壊: もしデータ自体に “ が含まれていた場合、それを検索したいという要件に対応できなくなる。
  • クエリプランのキャッシュ汚染: SQLエンジンはSQL文字列そのものをキーとしてキャッシュする。動的な文字列置換を多様すると、最適化が効かずパフォーマンスが低下する。
  • 保守性の欠如: SQL生成ロジックと、エンジン依存の変換ロジックが混在することで、将来的なクラウド移行やDB変更時に修正箇所が爆発する。

我々が目指すべきは、「SQL生成の責務」と「ワイルドカード変換の責務」を分離したラッパー設計である。

—

2. 堅牢なワイルドカード変換ラッパーの実装

DAO(Accessネイティブ)とADO(SQL Server等)を切り替えて運用している場合、接続先情報に基づいてワイルドカードを判定する関数を挟むのが定石だ。

実践:Engine-Aware Wildcard Wrapper

以下のコードを標準モジュールに配置し、SQL生成ロジックの「入り口」として活用してほしい。

‘ —————————————————————————
‘ 関数名: GetWildcard
‘ 概要: 接続先エンジンに基づき、適切なワイルドカード文字を返却する
‘ 引数: isSqlServer – TrueならSQL Server用(%), FalseならAccess用()
‘ —————————————————————————
Public Function GetWildcard(Optional ByVal isSqlServer As Boolean = False) As String
GetWildcard = IIf(isSqlServer, “%”, “”)
End Function

‘ —————————————————————————
‘ 使用例: SQL生成ロジックの一部
‘ —————————————————————————
Public Sub Example_GenerateSQL()
Dim isRemote As Boolean: isRemote = True ‘ 接続先判定ロジックをここに置く
Dim wc As String: wc = GetWildcard(isRemote)

‘ パラメータクエリを利用した堅牢なSQL生成(SQLインジェクション対策)
Dim sql As String
sql = “SELECT FROM T_Master WHERE Name LIKE @Name”

‘ パラメータ値の構築(例: “田中” で始まる検索)
Dim paramValue As String
paramValue = “田中” & wc

‘ ここで作成したパラメータをCommandオブジェクトに渡す
‘ …
End Sub

—

3. プロダクション環境における「3つの鉄則」

コードをコピペするだけで満足してはいけない。実務で生き残るための設計方針を共有する。

① パラメータクエリを絶対視せよ

文字列結合でSQLを作るのは、現代の開発において「無防備な脆弱性」に等しい。`QueryDef` オブジェクトまたは `ADODB.Command` オブジェクトを使用し、`Parameters` コレクションを介して値を渡すこと。これにより、ワイルドカードの変換問題もクエリ側で安全に解決される。

② 接続先情報の外部化

`isSqlServer` をハードコーディングするな。接続文字列(Connection String)を解析し、`Provider` が `SQLOLEDB` なのか `Microsoft.ACE.OLEDB` なのかを起動時に一度だけ判定し、パブリックな定数またはプロパティとして保持せよ。

③ 「あいまい検索」のUI仕様を統一せよ

ユーザーに対して「“ を使ってください」と強いるのはシステム側の敗北だ。UI上の検索ボックスでは常に “ を受け付け、バックエンドへの送信直前に変換する。この「変換層」をビジネスロジックの最外縁(DataAccess層)に配置することで、クエリ内部のロジックは常にクリーンに保たれる。

—

最後に:エンジニアとしての矜持

Access VBAはレガシーと言われることもあるが、その内部にあるDAO/ADOの堅牢な仕様を理解すれば、これほど強力なツールはない。動的SQLを単なる文字列として扱うのではなく、「エンジンに対する命令」として抽象化する意識を持ってほしい。

この設計を取り入れるだけで、あなたの書くコードは「動くもの」から「運用に耐えうる資産」へと進化するはずだ。

次は、この設計を拡張し、ストアドプロシージャとの連携においてワイルドカードをどうハンドリングすべきか、より高度なレイヤーの話をしよう。準備ができたら、またこの場所で会おう。

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