【入門編】ADOのCursorLocationプロパティの罠:ClientとServerの挙動を理解する – Access VBA解析バイブル

スポンサーリンク
スポンサーリンク

【Access VBAの深淵】ADOのCursorLocationが引き起こす「見えない罠」を解き明かす

こんにちは。業務自動化の荒波を共に乗り越えていく、あなたのパートナーです。

マクロの記録から一歩踏み出し、「もっと自由に、もっと高度にデータを操りたい」とADO(ActiveX Data Objects)に手を出し始めたあなた。素晴らしい一歩ですね。DAO(Data Access Objects)とはまた違う、ネットワーク越しにデータをやり取りするADOのパワーを感じ始めている頃ではないでしょうか。

しかし、ここで多くのプログラマーが、「なぜか更新できない」「なぜか動作が異常に重い」という、正体不明の壁にぶち当たります。

その壁の正体、実はコードの書き方ではなく、「データが今、どこに存在しているか」という、設計の根幹に関わる設定にあることが多いのです。

今日は、ADOを扱う上で避けては通れない、しかし多くの人が見落としてしまう`CursorLocation`プロパティという概念について、その本質を徹底的に解説していきましょう。ここをマスターすれば、あなたのVBAは「動くだけのコード」から「プロフェッショナルな設計」へと進化します。

1. そもそも「Cursor(カーソル)」とは何か?

技術的な詳細に入る前に、イメージを固めましょう。

データベースにおける「カーソル」とは、「今、レコードセットの中のどこを見ているか」という指差し確認の指のようなものです。

レコードセット(データの塊)を読み込むとき、コンピュータは「1件目のデータ」「2件目のデータ」と順番に見ていきます。この「今どこにいるか」を管理する仕組みがカーソルです。

そして、`CursorLocation`プロパティとは、「その『指』をどこに置くか?」を指定する命令なのです。

2. 二つの選択肢:Client と Server

`CursorLocation`には、大きく分けて2つの設定値があります。ここが運命の分かれ道です。

① adUseServer(サーバー・サイド・カーソル)

「指は、データの保管場所(サーバー)に置いたままにする」という設定です。

  • 挙動: あなたのPC(クライアント)は、「次の一件をください」とサーバーにリクエストを送るだけです。データの実体はサーバー側にあり、クライアントは最小限の情報しか持ちません。
  • メリット: クライアントのメモリをほとんど消費しません。数百万件という膨大なデータを扱う場合に適しています。
  • デメリット: データの移動(スクロール)のたびにネットワーク通信が発生するため、動作が「もっさり」しがちです。また、一部の環境では更新操作に制限がかかることがあります。

② adUseClient(クライアント・サイド・カーソル)

「指を、手元のPC(クライアント)に持ってくる」という設定です。

  • 挙動: サーバーからデータをガバッと一括でダウンロードし、あなたのPCのメモリ上に「コピー」を作成します。以降、データの移動はすべてあなたのPC内で行われます。
  • メリット: 一度ダウンロードしてしまえば、スクロールや検索が爆速です。また、データの更新操作も非常にスムーズに行えます。
  • デメリット: データを丸ごとメモリに乗せるため、大量のデータを取得しようとすると、あなたのPCのメモリを食いつぶし、Accessが強制終了(クラッシュ)する原因になります。

3. 【実戦】コードで見る挙動の違い

では、実際にどのようにコードで使い分けるのか見てみましょう。以下のサンプルコードは、設定によって挙動が変わることを意識して書いています。

Option Explicit

' ADOの参照設定(Microsoft ActiveX Data Objects x.x Library)が必要です
Sub TestCursorLocation()
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim strConn As String
    
    ' 接続文字列(ローカルのAccessファイルに接続する例)
    strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & CurrentProject.FullName & ";"
    
    Set cn = New ADODB.Connection
    cn.Open strConn
    
    Set rs = New ADODB.Recordset
    
    ' ==========================================================
    ' ここが運命の分かれ道!
    ' adUseClient : クライアント側にデータをコピー(高速・メモリ消費大)
    ' adUseServer : サーバー側で管理(低メモリ・通信発生)
    ' ==========================================================
    rs.CursorLocation = adUseClient 
    
    ' レコードセットを開く
    ' CursorTypeは、レコードの移動を自由にするために adOpenStatic を使用
    rs.Open "SELECT * FROM T_SampleTable", cn, adOpenStatic, adLockOptimistic
    
    ' --- データ操作の例 ---
    If Not rs.EOF Then
        Debug.Print "現在のレコード: " & rs.Fields(0).Value
        
        ' クライアントサイドなら、ここでの移動は非常に高速
        rs.MoveNext
        
        If Not rs.EOF Then
            Debug.Print "次のレコード: " & rs.Fields(0).Value
        End If
    End If
    
    ' --- 更新処理の例 ---
    ' adUseClient を使っていると、この更新がスムーズに成功しやすい
    ' (サーバーサイドだと、ロック競合などでエラーになるケースがある)
    ' rs.Fields(1).Value = "更新テスト"
    ' rs.Update
    
    ' 後始末
    rs.Close
    cn.Close
    Set rs = Nothing
    Set cn = Nothing
    
    MsgBox "処理が完了しました。イミテーション(コピー)を操作したか、実体を操作したかの違いを意識してください。", vbInformation
End Sub

4. 陥りやすい「罠」と回避策

プロの現場でよく遭遇するトラブルを、アーキテクトの視点で整理しておきましょう。

罠その1:「更新できない(Read-Only)エラー」

`adUseServer` を使用しているとき、特定のクエリや複雑な結合(JOIN)を含むレコードセットを開くと、ADOが「これは更新できないデータだ」と判断してしまい、更新不可(Read-only)になることがあります。

  • 対策: 基本的に、ユーザーが画面上でデータを編集するようなインターフェースを作る場合は、`adUseClient` を選択するのが定石です。

罠その2:「メモリ不足によるクラッシュ」

「とりあえず速いから」と、何でもかんでも `adUseClient` にしていませんか? 100万件のログテーブルを `adUseClient` で開いた瞬間、あなたのPCのメモリは悲鳴を上げ、Accessは沈黙します。

  • 対策:
  • 編集用(画面表示用) $\rightarrow$ `adUseClient`
  • 集計・一括処理用(バックエンド処理) $\rightarrow$ `adUseServer` または、そもそもレコードセットを開かずに `UPDATE` 文を直接発行する。

罠その3:「切断されたレコードセット(Disconnected Recordset)の活用忘れ」

`adUseClient` の真の力は、「データベースとの接続を切っても、手元のメモリ上のデータは保持できる」という点にあります。
接続を維持したまま長時間待機させるのではなく、データを `adUseClient` で取得 $\rightarrow$ 接続を閉じる $\rightarrow$ メモリ上で加工 $\rightarrow$ 再接続して書き戻す。この流れができると、ネットワーク負荷を劇的に抑えられます。

まとめ:エンジニアとしての判断基準

最後に、あなたが現場で迷ったときの指針を授けます。

シチュエーション 推奨される CursorLocation 理由
ユーザーが入力・編集するフォーム `adUseClient` 操作感(スクロール・更新)を最優先するため
大量データのバックグラウンド集計 `adUseServer` メモリ消費を抑え、システム全体の安定を図るため
ネットワークが不安定な環境での利用 `adUseClient` 一度取得すれば、通信断の影響を受けにくいため

「なんとなく動いたからOK」の段階を卒業し、「なぜこの設定を選んだのか」を論理的に説明できる。それが、真のプロフェッショナルへの道です。

この知識を武器に、より堅牢で、より高速なシステムを構築していってください。応援していますよ!

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