【実務・中級編】複雑な抽出条件を「JSON形式」で保存し、QueryDefのパラメータに変換して実行する仕組み – Access VBA解析バイブル

スポンサーリンク

Access VBAの限界を突破せよ:JSON駆動型QueryDefによる「動的検索エンジン」の構築

多くの開発者が、検索画面を作るたびに`WHERE`句を文字列結合で組み立てるという「アンチパターン」に陥っています。`”WHERE ID = ” & Me.txtID` といったコードは、SQLインジェクションの脆弱性を生むだけでなく、デバッグ不可能なスパゲッティコードの温床です。

本稿では、複雑な検索条件をJSONで一元管理し、Accessのネイティブ機能である`QueryDef`とパラメータークエリを融合させた、「堅牢かつ保守可能な動的検索システム」の設計思想を伝授します。

—

1. なぜ「文字列結合」を捨て、JSONとQueryDefに移行すべきか

SQLを文字列として生成すると、以下の問題が必ず発生します。

  • 型変換の地獄: 日付の `#` 囲み、文字列の `’` エスケープ忘れによるエラー。
  • クエリプランの非効率: 毎回異なる文字列が生成されるため、データベースエンジンが実行計画をキャッシュできず、パフォーマンスが低下する。
  • メンテナンス性の欠如: 画面数が増えるたびに、類似のSQL生成ロジックが散乱する。

我々アーキテクトが目指すべきは、「条件のデータ化」と「クエリの固定化」の分離です。JSONで条件を定義し、QueryDefのパラメーターとして渡すことで、SQLエンジンは常に同一のクエリプランを再利用でき、安全性も担保されます。

—

2. アーキテクチャの全体像

1. JSON層: 検索条件を `{“Key”: “Value”}` 形式の文字列として保持。
2. 解析層: VBAの `ScriptControl` または `VBA-JSON` (JSONConverter) を使い、条件をDictionaryオブジェクトに変換。
3. 実行層: `QueryDef` オブジェクトの `.Parameters` コレクションに値を注入し、レコードセットを開く。

—

3. 実装:プロフェッショナル・コード例

※事前に [VBA-JSON](https://github.com/VBA-tools/VBA-JSON) をインポートしておくことを推奨します。

ステップ1: パラメータークエリの準備

Access上で以下のSQLを保存してください(クエリ名: `qry_DynamicSearch`)。

PARAMETERS [p_Category] Text(255), [p_MinPrice] Long;
SELECT FROM T_Products
WHERE Category = [p_Category] AND Price >= [p_MinPrice];

ステップ2: 動的実行エンジン

このモジュールが、あなたのシステムの検索エンジンとなります。

Public Sub ExecuteDynamicSearch(jsonCriteria As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim jsonDict As Object

‘ 1. JSON解析
Set jsonDict = JsonConverter.ParseJson(jsonCriteria)

Set db = CurrentDb
Set qdf = db.QueryDefs(“qry_DynamicSearch”)

‘ 2. パラメーターの注入(型安全)
‘ 文字列結合を一切行わないことが重要
qdf.Parameters(“p_Category”) = jsonDict(“category”)
qdf.Parameters(“p_MinPrice”) = jsonDict(“min_price”)

‘ 3. レコードセットの実行と活用
Dim rs As DAO.Recordset
Set rs = qdf.OpenRecordset(dbOpenSnapshot)

‘ ここでフォームのレコードソースに設定するなど
‘ Set Me.Recordset = rs

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

rs.Close
Set rs = Nothing
Set qdf = Nothing
End Sub

—

4. 運用上の極意と注意点

パフォーマンスの最適化

`QueryDef` を使用する最大の利点は、「コンパイル済みのクエリ」であることです。`DoCmd.RunSQL` や `CurrentDb.Execute` で動的SQLを投げ続けるような野蛮な設計は今すぐ止めてください。`OpenRecordset` を使うことで、接続のオーバーヘッドを最小限に抑えられます。

JSONの設計ルール

  • 構造のフラット化: JSONはあまり深くネストさせないこと。Accessのパラメーター数は最大255個までですが、保守性を考えると10〜20個程度に収めるのが「プロの境界線」です。
  • Null値のハンドリング: JSON上の値がNullの場合、Dictionaryから取り出す際に `vbNullString` ではなく `Null` 型として明示的に渡すよう、変換層でラッパー関数を用意してください。

なぜこれが「負けない」設計なのか

将来的に検索条件が増えたとき、あなたはSQLを書き換える必要はありません。
1. クエリの `PARAMETERS` 句に項目を追加。
2. SQLの `WHERE` 句を調整。
3. VBA側で `qdf.Parameters` を1行追加するだけ。

この「疎結合」こそが、数年間にわたって運用される業務システムの生命線です。

—

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

VBAはレガシーと呼ばれることもありますが、その心臓部であるDAO(Data Access Objects)の設計は極めて堅牢です。JSONとQueryDefを組み合わせる手法は、現代的なWeb API開発の思想をAccessに持ち込む試みに他なりません。

「動けばいい」というコードで満足せず、「誰が読んでも意図が明確で、かつ変更に強い」コードを書いてください。それが、真に価値のある業務自動化エンジニアの姿です。

何か疑問があれば、いつでもコードを見せに来てください。修正が必要な箇所があれば、徹底的にレビューしましょう。

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