✅ はじめに
Access VBAでOO4O(Oracle Objects for OLE)からADO(ActiveX Data Objects)へ移行中、こんな現象に直面したことはありませんか?
SQLはそのまま使っているのに、ADOに変えたら処理がフリーズする
Recordset.Open のあとの If rs.EOF Then に進まない
ループや再帰があるわけでもないのに無限待機状態になる
このような場合、ADO特有の初期設定の違いが原因となっているケースがあります。
今回は、実際に発生した事例とその解決方法をご紹介します。
■ フリーズを引き起こしていたコード
Set rs = New ADODB.Recordset
rs.Open mySQL, g_con, 1, 1 ' adOpenKeyset, adLockReadOnly
If rs.EOF Then
一見普通の書き方ですが、このコードで処理が止まり、何も起こらない状態になる現象が発生しました。
〇 現象のポイント
・SQLに問題はない(OO4O時代は動いていた)
・ADO接続自体も成功している(g_con は正しくオープン済み)
・なのに EOF 判定にすら入らない
〇 原因:ADOのカーソル位置(CursorLocation)の初期値
ADOでは、Recordset の CursorLocation プロパティがデフォルトで adUseServer(=2) になっています。
これにより、サーバ側カーソルが使われ、Oracleなどのドライバとの相性でフリーズする場合があります。
■ 解決策:カーソルの場所を「クライアント側(adUseClient)」に指定する
修正後のコードは以下の通りです:
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.Open mySQL, g_con, 1, 1 ' adOpenKeyset, adLockReadOnly
If rs.EOF Then
■ adUseClient のメリット:
・クライアント側にデータを持つため、EOF判定や並べ替え、フィルタ処理が安定
・Oracleなど一部のプロバイダとの不整合を回避できる
・データ量が小さい処理ではパフォーマンス上も問題なし
■ 補足:なぜOO4Oでは問題なかったのか?
OO4Oでは、カーソルの概念がADOほど明示的ではなく、Oracleに特化した設計になっていたため、
サーバーとカーソルの整合性が自動で取られていました。
一方、ADOは汎用的なインターフェースであり、明示的にカーソルを指定しないと想定外の挙動をすることがあります。
■ まとめ
OO4OからADOへの移行で、以下のような「原因不明のフリーズ」が発生したら、まず疑うべきはカーソル設定です。
■ チェックポイント:
・Recordset を開く前に CursorLocation = adUseClient を設定したか?
・OracleなどのOLE DBプロバイダとの相性を確認したか?
・旧OO4O環境とADO環境で、暗黙的な動作が違う可能性を認識しているか?
SQLを変えていないのにフリーズするなら、それはADOのデフォルト設定が影響している可能性が高いです。
■ 次の一手:
・一時的に adUseServer で動いている場合でも、最初から adUseClient に統一しておく方が安全
・フリーズ解消後は、接続オプションやプロバイダ固有の動作も確認しておくと、さらなるトラブル予防になります