Access VBAを掌握せよ:DAO.Recordsetの「型不一致」と「ロック競合」を制するアーキテクチャの極意
Access開発の現場で、多くのエンジニアが「なんとなく」で済ませている箇所がある。それは`OpenRecordset`メソッドだ。
「とりあえずデータが取れればいい」と引数を省略したり、適当な定数で済ませていないだろうか? その甘えが、マルチユーザー環境でのロック競合や、謎の「型不一致」エラー、そして目に見えないパフォーマンス低下を引き起こす。
今日は、DAOのアーキテクチャを深層から理解し、堅牢で高速なシステムを構築するための「型指定の極意」を伝授する。
—
1. なぜ「型指定」が運命を分けるのか
`OpenRecordset`の第2引数(Type)と第3引数(Options)は、Accessがデータベースエンジン(ACE/Jet)とどう対話するかを決定する「契約書」だ。
ここを明示しないと、Accessは「とりあえずデフォルトで動く設定」を推測する。だが、この推測こそがバグの温床だ。
- `dbOpenDynaset` (動的セット): 編集可能。クエリの結合や複雑な条件がある場合に最適。
- `dbOpenSnapshot` (スナップショット): 読み取り専用。静的なデータを扱う場合、最も高速でサーバー負荷も低い。
- `dbOpenTable` (テーブルタイプ): テーブルに直接アクセスする。インデックスが効く範囲内では最速だが、リンクテーブルには使えない。
「型不一致」が発生する最大の理由は、「読み取り専用のクエリに対して、更新権限のあるカーソルを開こうとする」といった、データベースの物理的な制約とコードの意図が矛盾した時に起こる。
—
2. 現場で生き残るための「鉄則設計」
実務で「落ちないコード」を書くための戦略はシンプルだ。
1. 目的を明確にせよ: 編集するのか、参照するだけか。参照だけなら例外なく`dbOpenSnapshot`を指定する。これだけでロックのオーバーヘッドがゼロになる。
2. インデックスを信じよ: `dbOpenTable`を使える場面では積極的に使う。ただし、リンクテーブルに対しては使用不可という制限を忘れてはならない。
3. エラーハンドリングを標準装備せよ: DAOは外部リソースを叩く。`Err.Number`を監視し、特にロック競合(3021, 3055等)はリトライ処理を設計に組み込むのがプロの流儀だ。
—
3. 【プロダクションコード】堅牢なRecordset操作のテンプレート
以下は、保守性を最大限に高めた、実務でそのまま使えるDAO操作のテンプレートだ。
‘ @description 安全かつ高速にレコードセットを開くための標準関数
Public Function GetSafeRecordset(sql As String, Optional ByVal useSnapshot As Boolean = True) As DAO.Recordset
Dim db As DAO.Database
Dim rs As DAO.Recordset
On Error GoTo ErrorHandler
Set db = CurrentDb
‘ 読み取り専用ならSnapshot、そうでなければDynaset(排他制御を考慮)
If useSnapshot Then
Set rs = db.OpenRecordset(sql, dbOpenSnapshot, dbReadOnly)
Else
‘ 更新用なら必要に応じて dbSeeChanges を付与(SQL Server等のバックエンド対策)
Set rs = db.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges)
End If
Set GetSafeRecordset = rs
Exit Function
ErrorHandler:
‘ ログ出力やエラーハンドリングをここに記述
Debug.Print “Error: ” & Err.Number & ” – ” & Err.Description
Set GetSafeRecordset = Nothing
End Function
このコードのポイント
- `dbReadOnly`の明示: スナップショットを開く際にこれを追加することで、予期せぬ更新試行を未然に防ぐ。
- `dbSeeChanges`の考慮: SQL ServerやAzure SQL等のクライアント/サーバー構成では必須。これを忘れると、他ユーザーの更新と衝突した瞬間にアプリがクラッシュする。
- 再利用性: 接続先を`CurrentDb`に固定せず、引数で渡せるように設計すると、将来的な分割DB構成への移行もスムーズになる。
—
4. 最後に:エンジニアとしての矜持
VBAはレガシーと言われることもある。しかし、正しく設計されたDAOのアーキテクチャは、現代のどの高レベル言語にも負けないほど、Accessという土壌で完璧に機能する。
「動いたからOK」ではない。「なぜその型で開く必要があるのか」を言語化できるエンジニアこそが、現場を救う。
次回は、このRecordsetとADOを組み合わせた、より大規模なトランザクション制御の極意について解説する予定だ。君のコードに、妥協のないアーキテクチャを実装してほしい。
