こんにちは!Access VBAの世界へようこそ。
マクロの記録から一歩踏み出し、「自分でコードを書いてシステムをコントロールしたい!」という熱意を持つあなたへ、今日はとてもエキサイティングで実用的なテーマをお届けします。
ここをクリアすれば、複数人で使うAccessデータベースの「更新トラブル」をスマートに回避できるようになり、あなたの作るアプリの信頼性は劇的に跳ね上がります。ぜひ最後までついてきてくださいね!
—
1. 現場のリアル:なぜ「同時更新」でエラーが起きるのか?
私たちが作るAccessアプリが社内で使われ始めると、必ずと言っていいほど直面するのが「マルチユーザー環境の壁」です。
例えば、こんなシチュエーションを想像してください。
- あなたが「商品A」の在庫数を「10」から「15」に変更しようと画面を開いています。
- ほぼ同じタイミングで、営業部のA君も「商品A」のデータを参照し、価格を「1,000円」から「1,200円」に変更して保存しました。
- その直後、あなたが在庫数を「15」にして保存ボタンを押しました。
…さあ、どうなるでしょうか? A君が変更した「価格:1,200円」は消えてしまうのでしょうか? それともエラーで弾かれるのでしょうか?
Accessのデータエンジン(DAO)は、こうした「他のユーザーによる裏での変更」をどう扱うかを、私たちプログラマが細かく指定できる仕組みを持っています。それが今回学ぶ`dbConsistent`(一貫性保持)と`dbInconsistent`(不整合許可)という、ちょっとカッコいい更新オプションです。
—
2. アーキテクチャの核心:dbConsistent と dbInconsistent の正体
DAO(Data Access Objects)を使ってレコードセットを更新するとき、私たちは `Update` メソッドを使いますよね。実はこの時、裏側で「他の人がデータを書き換えていたらどうするか?」の判定が行われています。
ざっくり言うとこういうこと!
- `dbConsistent` (デフォルト・厳格派)
「私がこのレコードを読み込んでから、誰か他の人が1つでもフィールドを書き換えていたら、私の更新は全体まるごとエラーにする!(データの矛盾を絶対に許さない)」
- `dbInconsistent` (寛容派)
「私が読み込んでから他の人が別のフィールドを変えていても、私が触っていないフィールドなら上書きしてOK! ただし、同じフィールドを同時に変えていたら、後から書き込んだ方が勝つ(あるいは競合する)」
特に、Accessでよく使われる「結合クエリ(JOINを使ったクエリ)」をプログラムから更新するとき、この違いがモロに影響してきます。
—
3. 実践!コードで見る更新競合の制御
百聞は一見にしかず。実際のコードを見てみましょう。
ここでは、受注テーブルと顧客テーブルを結合したクエリに対して、あえて更新オプションを指定してデータを書き換えるプロシージャを書きます。
Sub UpdateWithConflictControl()
Dim db As DAO.Database
Dim rs As DAO.Recordset
‘ 現在のデータベースを取得
Set db = CurrentDb
On Error GoTo ErrorHandler
‘ 【ポイント】結合クエリに対してレコードセットを開く
‘ dbDenyWriteを指定して、自分以外の更新を一時的にブロックしつつ開く例
Set rs = db.OpenRecordset(“Q_受注と顧客”, dbOpenDynaset, dbDenyWrite)
If rs.EOF Then
MsgBox “対象データが見つかりません。”, vbExclamation
GoTo Cleanup
End If
‘ 編集モードに移行
rs.Edit
‘ データの書き換え
rs!受注数量 = 100
rs!備考 = “システムから一括更新”
‘ 【重要】ここで更新オプションを指定して保存!
‘ 今回はデータの矛盾を絶対に防ぐために 「dbConsistent」 を指定
rs.Update dbConsistent
MsgBox “データの更新が正常に完了しました!”, vbInformation
Cleanup:
‘ オブジェクトの解放(メモリリークを防ぐプロの作法)
If Not rs Is Nothing Then rs.Close
Set rs = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
‘ 競合が発生した場合のエラー番号は 3197 など
If Err.Number = 3197 Then
MsgBox “他のユーザーによってデータが変更されています。” & vbCrLf & _
“最新のデータを取得し直してから再度やり直してください。”, vbCritical, “更新競合エラー”
Else
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
End If
Resume Cleanup
End Sub
コードのここがポイント!
1. `dbOpenDynaset`: 動的集合(ダイナセット)として開くことで、他のユーザーの変更を反映できる状態にしています。
2. `rs.Update dbConsistent`: ここで「一貫性」を強制しています。もしあなたがデータをいじっている間に、別の人やプロセスが同じレコードを触っていた場合、エラートラップ(`Err.Number = 3197` など)が鮮やかにそれをキャッチしてくれます。
—
4. 陥りやすい罠とエンジニアからのアドバイス
初学者の頃、よくやってしまう失敗が「エラー処理をサボること」です。
マルチユーザー環境のAccessアプリで、`dbConsistent` を使っていると、システムが本番稼働してデータ量が増えた途端に、ユーザーから「なんか急にエラーが出るんだけど!」と連絡が来るようになります。これはバグではなく、正常な排他制御の証拠です。
現場で役立つ設計のコツ
- 基本は `dbConsistent`(一貫性重視)を使おう
ビジネスデータにおいて「知らぬ間に値が書き換わっていた」という現象(不整合)は、後々大トラブルに繋がります。基本は安全第一の `dbConsistent` を選びましょう。
- エラーが起きたときの「優しい導線」を作る
エラー番号 3197(または関連する競合エラー)をキャッチしたら、単にプログラムを止めるのではなく、「画面のデータを最新の状態にリフレッシュ(`rs.Requery` など)する仕組み」をセットで用意してあげると、現場のユーザーから神様扱いされますよ。
—
まとめ
いかがでしたでしょうか?
DAOの `dbConsistent` と `dbInconsistent` は、一見すると地味なオプションに見えますが、「複数人で安全にデータを共有する」というデータベースの根幹を支える非常に重要なスパイスです。
ここを理解したあなたなら、単に動くだけのコードではなく、「実務の荒波に耐える堅牢なシステム」が作れるようになっています。
ここをクリアすれば、Access VBAの基本はもうバッチリです!自信を持って次のステップへ進んでくださいね。応援しています!
