Access VBAの暗黒面を制御せよ:ADO CursorLocationが引き起こす「見えない地獄」の正体
現場で「Accessが重い」「ネットワークが詰まる」と嘆くエンジニアのコードを覗くと、決まってADOの接続設定が適当だ。特に`CursorLocation`の選択を「なんとなく」で行っているなら、君は自分の足元に時限爆弾を仕掛けているに等しい。
今日は、DAOの時代から一歩進み、ADOを駆使して堅牢な業務システムを構築する君のために、`adUseClient`と`adUseServer`の「境界線」を論理的に解説する。
—
1. そもそもCursorLocationとは何か?
ADOでレコードセットを開く際、`CursorLocation`は「誰がデータを管理し、どこで処理するか」を決定する司令塔だ。
- `adUseServer`(サーバーサイドカーソル): データベースエンジン(SQL Server等)がカーソルを管理する。
- `adUseClient`(クライアントサイドカーソル): データを一度ローカルメモリ(VBA実行環境)に引き抜いてから管理する。
多くのエンジニアが「サーバーがやってくれるなら`adUseServer`の方が速いだろう」と誤解する。だが、Access VBAにおいてその認識は致命的な設計ミスを招く。
—
2. なぜ「adUseClient」が正義なのか(実務的視点)
ネットワーク越しにSQL Server等へ接続する場合、`adUseServer`は「行単位」でサーバーと通信を行う。1000行のスクロールで1000回の往復が発生することを想像してほしい。ネットワークのレイテンシが君のアプリを殺す。
対して`adUseClient`は、「全データを一気にメモリへ転送(バルク転送)」する。
- メリット: ネットワークの往復回数が激減し、ソートやフィルタリングをローカルCPUで爆速処理できる。
- 代償: メモリ消費量が増大する。巨大なデータを安易に扱うとAccessが落ちる。
結論: 業務ツールにおいては、「必要な分だけ抽出条件を絞り込み、`adUseClient`でローカルメモリへ引き抜く」のが、最も堅牢かつパフォーマンスが高い構成だ。
—
3. 実装:保守性を担保したプロダクションコード
コピペで動くだけのコードはゴミだ。ここでは「コネクションの解放」と「エラーハンドリング」を徹底した、保守可能なテンプレートを提示する。
‘ ———————————————————
‘ 関数名: GetRecordsetClientSide
‘ 目的: SQLServerからクライアントカーソルでデータを安全に取得する
‘ ———————————————————
Public Function GetRecordsetClientSide(ByVal strSQL As String, ByVal connString As String) As ADODB.Recordset
Dim rs As ADODB.Recordset
Dim conn As ADODB.Connection
On Error GoTo ErrorHandler
Set conn = New ADODB.Connection
conn.ConnectionString = connString
conn.Open
Set rs = New ADODB.Recordset
‘ ここが極意:サーバーではなくクライアントで管理させる
rs.CursorLocation = adUseClient
‘ 切断型レコードセットを作成(接続を閉じてもデータは保持される)
rs.Open strSQL, conn, adOpenStatic, adLockReadOnly
Set rs.ActiveConnection = Nothing ‘ コネクションを切断してメモリ負荷を軽減
Set GetRecordsetClientSide = rs
‘ クリーンアップ
conn.Close
Set conn = Nothing
Exit Function
ErrorHandler:
MsgBox “データベース接続エラー: ” & Err.Description, vbCritical
If Not conn Is Nothing Then conn.Close
Set conn = Nothing
End Function
—
4. トランザクション処理の鉄則
`adUseClient`を選択した場合、トランザクション管理は接続(Connection)に対して行う必要がある。
注意すべきは、`adUseClient`で更新を行うと「バッチ更新」モードになりやすい点だ。`rs.UpdateBatch`を実行するまでサーバーに書き込まれない。この間、排他制御の責任は君のコードにある。
- 鉄則: トランザクションは最小範囲で。
- 鉄則: ネットワークエラーを想定し、必ず`RollbackTrans`をエラーハンドラに入れること。
—
5. チーフアーキテクトからの助言
「サーバーの負荷を下げたいから`adUseServer`を使う」という考え方は、Accessクライアントが主体となるシステムでは自己満足に過ぎない。
1. データ量が数万件を超えないなら: `adUseClient`一択。ローカル処理の安定性は圧倒的だ。
2. データ量が膨大なら: Accessに全データを渡すな。SQL Server側でViewを作成し、必要な結果セットだけを抽出せよ。
3. メモリ管理: `Set rs = Nothing` を忘れるのはプロ失格だ。オブジェクトのライフサイクルを意識せよ。
Accessは「ファイルベースのデータベース」と思われがちだが、ADOを正しく使えば、エンタープライズ級のフロントエンドに変貌する。「どこで、誰が、どう管理するか」。この問いを常に持ち続けることこそが、伝説のエンジニアへの第一歩だ。
健闘を祈る。何かあればまた聞きに来い。
