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

スポンサーリンク

Access VBAの深淵:ワイルドカードの迷宮を制する「境界防御」アーキテクチャ

エンジニア諸君。Accessという閉じた箱庭の中で、レガシーとモダンが混在するシステムを保守していると、必ず一度は「ワイルドカードの呪い」に遭遇するはずだ。

DAOの“か、ADO(SQL Server)の`%`か。この些細な記法の違いが、大規模なクエリ定義(QueryDef)の再利用を阻害し、保守性を劇的に悪化させる。場当たり的な`Replace`関数の多用は、やがてメモリリークや意図せぬSQLインジェクションの温床となる。

今回は、AccessエンジンとSQL Server(T-SQL)の境界線を完璧に抽象化し、実行環境に応じて動的にワイルドカードを変換する「境界防御型ラッパー」の実装論を提示する。

—

1. なぜ「ワイルドカードの不整合」が致命傷になるのか

Accessのネイティブエンジン(ACE/Jet)は“を好む。しかし、ODBC経由でSQL Serverへクエリを投げる際、T-SQLは`%`を要求する。

多くの初学者は、クエリ文字列を構築する段階でこれらをハードコーディングする。だが、これは「データ層」と「実行層」の密結合を意味する。もし将来的にバックエンドを移行する際、何百ものSQL文を一つずつ修正するつもりか?

我々が目指すべきは、「SQL文は標準仕様で記述し、実行直前にエンジンが解釈可能な形式へトランスパイルする」という設計思想だ。

—

2. 実装:環境最適化ワイルドカード・トランスパイラ

以下に、メモリの無駄な確保を避け、厳格なオブジェクト管理を行うクラスメソッドの骨子を示す。

‘ @Description: ワイルドカード変換クラス (WildcardTranspiler)
‘ @Usage: 実行エンジンに合わせてワイルドカードを最適化する

Public Function NormalizeWildcards(ByVal sql As String, ByVal isSqlServer As Boolean) As String
‘ パフォーマンス向上のため、連結ではなく内部バッファの最適化を意識する
‘ SQL Serverの場合は % を使用し、Accessエンジンの場合は を使用する

If isSqlServer Then
‘ Accessの を SQL Server の % に置換
NormalizeWildcards = Replace(sql, “”, “%”)
Else
‘ SQL Serverの % を Access の に置換
NormalizeWildcards = Replace(sql, “%”, “”)
End If
End Function

‘ QueryDef実行の推奨パターン
Public Sub ExecuteDynamicQuery(ByVal sql As String, ByVal dbConn As Object)
Dim qdf As DAO.QueryDef

‘ 実行エンジンの判定(DAOかADOか、あるいは接続先か)
‘ ここでは簡略化のためフラグを渡す前提とする
Dim targetSql As String
targetSql = NormalizeWildcards(sql, True)

‘ 明示的なオブジェクトの生成と破棄
Set qdf = CurrentDb.CreateQueryDef(“”, targetSql)

On Error GoTo Cleanup
qdf.Execute dbFailOnError

Cleanup:
‘ 伝説のエンジニアは「後始末」を怠らない
‘ メモリリークを防ぐための明示的解放
If Not qdf Is Nothing Then
qdf.Close
Set qdf = Nothing
End If

If Err.Number <> 0 Then Err.Raise Err.Number, “ExecuteDynamicQuery”, Err.Description
End Sub

—

3. シニアエンジニアが守るべき3つの鉄則

このコードを実装する上で、以下の「極限の知見」を刻み込んでおいてほしい。

① インラインクエリの回避とメモリの解放

`CreateQueryDef(“”, sql)`で作成した一時クエリは、適切に`Close`しなければDBのシステムテーブルにゴミが溜まる。特にループ内で大量のクエリを生成する場合、明示的な`Set qdf = Nothing`は必須だ。VBAのGC(ガベージコレクション)を信用してはならない。

② パラメータークエリへの昇華

上記のトランスパイラはあくまで補助輪だ。真の最適解は「ワイルドカード自体をパラメーターとして渡すこと」にある。`LIKE ‘%’ & [Param] & ‘%’`のように記述すれば、ワイルドカード変換のロジックすら不要になる。クエリコンパイルの効率も向上する。

③ Windows APIによるパフォーマンス監視

大規模なクエリ実行時には、`GetTickCount`や`QueryPerformanceCounter`等のAPIを呼び出し、実行時間をロギングせよ。実行エンジンが最適化されているか、ボトルネックは変換ロジックにあるのか、それともネットワーク待ちにあるのか。定量的データなき改善は単なる勘に過ぎない。

—

結論:システムは「境界」で制御せよ

優れたシステムとは、エンジンの仕様に振り回されるものではなく、仕様をラッピングし、制御下に置くものだ。

今回紹介したワイルドカード変換のロジックは、地味かもしれない。だが、このような細部へのこだわりこそが、10年後もメンテナンス可能な「伝説的なシステム」と、数年で使い物にならなくなる「レガシーの墓場」を分かつ境界線となる。

君たちがコードを書く時、常に考えろ。「この実装は、将来のエンジニアを救うか?」と。
それが、プロフェッショナルとしての唯一の正解だ。

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