【入門編】DAOの「dbFailOnError」オプションを使いこなす:更新処理の安全性を高める隠れた切り札 – Access VBA解析バイブル

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

沈黙の失敗を許さない。DAOの「dbFailOnError」で手に入れる、プロのデータ整合性

「プログラムは動いているけれど、なぜかデータが中途半端に書き換わっている……」

Access VBAを学び始めた方が、最初に突き当たる「見えない壁」があります。それは、エラーメッセージすら出さずに、処理の一部だけが「こっそり失敗する」という現象です。

マクロの記録や、ネットで見つけたコードをそのままコピーして動かしている段階では、この恐怖には気づけません。しかし、実務で「在庫管理」や「売上集計」といった、1件のミスも許されないシステムを構築するなら、この「沈黙の失敗」を完全に封じ込める必要があります。

今日は、DAO(Data Access Objects)を扱うエンジニアにとっての「隠れた切り札」、`dbFailOnError` オプションについて、その本質を解き明かしていきましょう。ここをマスターすれば、あなたのコードは「ただ動くもの」から「信頼されるシステム」へと進化します。

1. なぜ「エラーが出ない失敗」が起きるのか?

まず、問題の核心を知ることから始めましょう。

例えば、あなたは「100人の従業員の給与を一括更新する」というプログラムを書いたとします。
プログラムは順調に動き、99人分の更新は成功しました。しかし、たった1人だけ、「入力された値が数値型ではない」といった理由で、データベースのルール(制約)に抵触してしまったとします。

このとき、標準的な書き方(`DoCmd.RunSQL` や、オプションを指定しない `DAO.Execute`)では、Accessはこう振る舞います。

> Accessの思考: 「おっと、50番目の人の更新はルール違反だね。じゃあ、その人だけ飛ばして、残りの人は更新を続けちゃおう。エラーは出さなくていいよね?」

これが「沈黙の失敗」です。
プログラムの実行結果は「成功」として終了しますが、実際にはデータが不完全な状態(整合性が崩れた状態)になっています。これが、業務システムにおいて最も恐ろしい事態なのです。

2. 救世主 `dbFailOnError` の正体

この「お節介なスルー」を許さず、「1件でも失敗したら即座にエラーを吐いて止まれ!」と命令するのが、`dbFailOnError` というオプションです。

これは、DAOの `Database.Execute` メソッドに渡すことができる「命令のフラグ」です。

図解:処理の違い

  • 通常時 (`dbSeeChanges` 等のみ、または指定なし)

`[成功] → [成功] → [失敗(スルー)] → [成功] → [完了(一見、成功!)]`
👉 結果:データが不整合になる(最悪)

  • `dbFailOnError` 使用時

`[成功] → [成功] → [失敗(即エラー発生!)] → [処理中断]`
👉 結果:どこで失敗したかが明確になり、不完全な更新を防げる

3. 実践:プロフェッショナルな書き方

それでは、実際にどのようにコードを書くべきか見ていきましょう。
「マクロの記録」から脱却した、エンジニアらしい堅牢なコードの書き方です。

❌ 避けるべき書き方(初心者によくあるパターン)

' DoCmd.RunSQL はユーザーに確認ダイアログを出したり、
' エラーが起きても「一部実行されました」という曖昧な挙動になりがちです。
DoCmd.RunSQL "UPDATE T_在庫 SET 在庫数 = 在庫数 - 1 WHERE 商品ID = 101"

✅ 推奨される書き方(プロのアーキテクチャ)

Sub UpdateStockSafe()
    Dim db As DAO.Database
    Dim strSql As String
    
    Set db = CurrentDb
    strSql = "UPDATE T_在庫 SET 在庫数 = 在庫数 - 1 WHERE 商品ID = 101"
    
    On Error GoTo ErrorHandler ' エラーハンドリングを必ずセットする
    
    ' 【ここが肝!】 dbFailOnError を指定することで、
    ' 1件でも制約違反があれば、即座にエラーイベントを発生させます。
    ' dbSeeChanges は、更新可能なクエリを実行する際に必須となるフラグです。
    db.Execute strSql, dbFailOnError + dbSeeChanges
    
    MsgBox "更新が正常に完了しました。", vbInformation
    
ExitSub:
    Set db = Nothing
    Exit Sub

ErrorHandler:
    ' エラーが発生した場合、ここへジャンプします。
    ' 失敗したまま処理が進むことを防ぎ、ユーザーに警告を出せます。
    MsgBox "更新に失敗しました!データは変更されていません。" & vbCrLf & _
           "エラー内容: " & Err.Description, vbCritical, "システムエラー"
    Resume ExitSub
End Sub

コードのポイント解説

1. `db.Execute …, dbFailOnError + dbSeeChanges`:
複数のオプションを組み合わせる際は `+` で繋ぎます。これにより、「失敗したらエラーを出せ」かつ「更新可能なクエリとして扱え」という二つの命令を同時に伝えています。
2. `On Error GoTo ErrorHandler`:
`dbFailOnError` は「エラーを発生させる」ためのスイッチです。発生したエラーをキャッチして、適切に処理(ユーザーへの通知やログ記録)するために、このエラーハンドリングはセットで必須となります。

4. さらに高みへ:トランザクションとの組み合わせ

ここまでで、「一つのSQL文の中での失敗」は防げるようになりました。
しかし、実務では「複数のSQL文を、すべて成功するか、すべて失敗するか(All or Nothing)のどちらかにしたい」という場面が多々あります。

例えば、「注文テーブルにデータを追加」し、次に「在庫テーブルを減らす」という2つの処理を行う場合。在庫を減らす処理で失敗したなら、注文の追加もキャンセルしなければなりません。

ここで登場するのが、トランザクション処理です。

Sub ComplexTransactionExample()
    Dim db As DAO.Database
    Set db = CurrentDb
    
    On Error GoTo TransactionError
    
    ' 1. トランザクションの開始(ここから「仮の更新」が始まる)
    DBEngine.BeginTrans
    
    ' 2. 注文の追加
    db.Execute "INSERT INTO T_注文 (商品ID, 数量) VALUES (101, 1)", dbFailOnError + dbSeeChanges
    
    ' 3. 在庫の更新(ここで失敗すると、2の処理も巻き戻される)
    db.Execute "UPDATE T_在庫 SET 在庫数 = 在庫数 - 1 WHERE 商品ID = 101", dbFailOnError + dbSeeChanges
    
    ' 4. すべて成功したら、確定させる
    DBEngine.CommitTrans
    MsgBox "すべての処理が正常に確定しました。", vbInformation

ExitSub:
    Set db = Nothing
    Exit Sub

TransactionError:
    ' 5. どこかでエラーが起きたら、すべての変更を「なかったこと」にする
    DBEngine.Rollback
    MsgBox "エラーが発生したため、すべての処理を取り消しました。" & vbCrLf & _
           "エラー内容: " & Err.Description, vbCritical
    Resume ExitSub
End Sub

アーキテクトの視点

  • `dbFailOnError` は「単発の弾丸の精度」を高めるもの。
  • `BeginTrans / CommitTrans` は「一連の作戦の成否」を管理するもの。

この二つを組み合わせることで、あなたのプログラムは、どんな過酷なデータ入力に対しても、データの整合性を守り抜く最強の盾を手に入れるのです。

まとめ:ここをクリアすれば、Access VBAの基本はバッチリですよ

「とりあえず動けばいい」という段階から、「データが絶対に壊れない仕組みを作る」というプロフェッショナルの段階へ。その境界線にあるのが、今回解説した `dbFailOnError` です。

1. `DoCmd.RunSQL` ではなく `db.Execute` を使う。
2. 必ず `dbFailOnError` オプションを添える。
3. `On Error GoTo` でエラーを捕まえる準備を忘れない。

この3点を守るだけで、あなたの作るシステムの信頼性は劇的に向上します。
一歩ずつ、着実に。コードの裏側にある「データの命」を大切にするエンジニアを目指していきましょう。応援していますよ!

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