【Access VBA極限道】SQL Serverの真価を引き出す「パススルー」の処方箋
Accessを「単なるローカルDB」と侮るなかれ。我々アーキテクトにとって、AccessはSQL Serverという巨大なエンジンを自在に操るための「高機能なフロントエンド」である。
しかし、多くの開発者が犯す致命的なミスがある。「Accessのリンクテーブルを介して、Accessエンジン上でJOINや集計を行う」という愚行だ。これでは、SQL Server側にある数百万レコードのデータが、ネットワークを流れてAccess側にダウンロードされてから処理される。ボトルネックは常にネットワーク帯域だ。
今日伝授するのは、SQL Serverのポテンシャルを解放し、処理を爆速化させる「パススルー・クエリ」の極限実装術である。
—
1. なぜ「パススルー」でなければならないのか?
通常のリンクテーブル経由のクエリは、AccessのJET(またはACE)エンジンがSQLを解釈し、最適化を試みる。しかし、複雑なストアドプロシージャや、SQL Server固有の関数を多用する場合、この「翻訳」コストが巨大な負荷を生む。
パススルー・クエリ(Pass-Through Query)とは、Accessのエンジンを完全にバイパスし、SQL文をそのままSQL Serverへ「直投げ」する手法だ。Accessは結果を受け取るだけの「単なる窓口」に徹する。これにより、SQL Server側で最適化された実行計画が即座に適用される。
—
2. 堅牢な設計:動的パススルー・クエリ実装術
実務では、動的なパラメータを伴う処理が必須となる。だが、QueryDefのSQLプロパティを直接書き換えるのは、マルチユーザー環境で競合を招くリスクが高い。
以下のコードは、「一時的なQueryDefを生成し、実行後に即座に破棄する」という、メモリと排他制御を考慮したプロダクション・グレードの設計である。
実装コード:ExecutePassThrough
‘ —————————————————————————
‘ @brief SQL Serverへ直接クエリを投げ、結果セットを返す
‘ @param sqlStr 実行するSQL ServerのT-SQL文
‘ @param connectStr 接続文字列(DAO.TableDefのConnectプロパティから取得推奨)
‘ —————————————————————————
Public Function ExecutePassThrough(ByVal sqlStr As String, ByVal connectStr As String) As DAO.Recordset
Dim qdf As DAO.QueryDef
‘ 一時的なQueryDefを作成(名前を空にすることで一時オブジェクトとして管理)
Set qdf = CurrentDb.CreateQueryDef(“”)
With qdf
.Connect = connectStr ‘ SQL Serverへの接続文字列
.SQL = sqlStr ‘ T-SQL本体
.ReturnsRecords = True ‘ 結果を返すクエリか否か
.ODBCTimeout = 60 ‘ タイムアウト設定(巨大データ時は調整)
‘ 非同期実行ではなく同期実行。結果セットを戻り値として返す
Set ExecutePassThrough = .OpenRecordset(dbOpenSnapshot)
End With
‘ オブジェクトの破棄(メモリ解放を徹底)
Set qdf = Nothing
End Function
—
3. 実務で「絶対に守るべき」3つの鉄則
コードを動かすことは容易い。しかし、エンジニアとして「壊れない」システムを構築するには、以下の原則を胸に刻め。
① 接続文字列のハードコーディングは死を意味する
接続文字列にパスワードを生で書くなど論外だ。リンクテーブルの `TableDefs(“任意のテーブル名”).Connect` から実行時に取得せよ。これにより、DBのパスワード変更やサーバー移行にも、ソースコード修正なしで対応できる。
② ODBCTimeoutを制御せよ
デフォルトのタイムアウト設定は、巨大な分析処理には短すぎる。SQL Server側の負荷状態を考慮し、処理内容に応じて `ODBCTimeout` を動的に設定する勇気を持て。
③ トランザクションと排他制御
パススルーで `UPDATE` や `DELETE` を行う場合、Accessのレコードロックは効かない。SQL Server側で `BEGIN TRANSACTION` を発行し、エラーハンドリング内で `ROLLBACK` を実行する堅牢な構造を構築すること。
—
4. アーキテクトからの提言:クエリの「重さ」を見極める
すべてをパススルーにすべきではない。
- 数千件程度の小規模なマスタ参照: リンクテーブルで十分。Accessのキャッシュが効く。
- 数百万件の集計、複雑な結合、ストアド実行: 迷わずパススルー。
ツール作成において最も重要なのは、「技術の使い分け」という名の哲学だ。Accessを「ただのデータベース」として使うのではなく、「SQL Serverを操るための強力なIDE(統合開発環境)」として捉え直したとき、あなたの作るシステムは次元の異なるパフォーマンスを発揮するはずだ。
さあ、コードを書き換えろ。ボトルネックは技術の問題ではない。あなたの設計思想の置き所にある。
