【入門編】DAO.Database.Executeの「dbFailOnError」オプションで更新失敗を検知する – Access VBA解析バイブル

スポンサーリンク

こんにちは! Access VBAの開発現場で、日夜データと格闘お疲れ様です。
今日は、Accessデータベースの信頼性を保つための「超・重要テクニック」についてお話ししますね。

マクロの記録から一歩踏み出し、VBAで本格的なデータ操作(INSERTやUPDATEなど)を行うようになると、避けて通れないのが「エラーとの向き合い方」です。

「ここをクリアすれば、Access VBAの基本はバッチリですよ!」と言えるほど大切な、DAOの真髄`dbFailOnError`について、シニアエンジニアの視点から魂を込めて解説します。

1. なぜ「静かに失敗する」SQLは恐ろしいのか?

VBAからSQL文を実行するとき、皆さんはどんな方法を使っていますか?
多くの入門書では、次のようなコードが紹介されているはずです。

‘ よくある実行コード
CurrentDb.Execute “UPDATE T_受注台帳 SET ステータス = ‘完了’ WHERE 注文ID = 9999”

一見、何の問題もないように見えますよね。
でも、プロの現場では、この書き方は「爆弾を抱えている」とみなされます。

なぜなら、この `CurrentDb.Execute` というメソッド、デフォルトでは「途中でエラーが起きようが、データが更新できなかろうが、知らん顔してスルーする」という仕様になっているからです。

例えば:

  • 更新しようとしたレコードが、別のユーザーにロックされていた
  • 外部キー制約(リレーションシップ)に違反するデータを書き込もうとした
  • フィールドの型エラーや、文字数オーバーが発生した

こんな時でも、`dbFailOnError` を指定しないと、エラーメッセージすら出さずに「平然と次の行のコードへ進んでしまう」のです。気がついた時には、データベースの一部だけが書き換わり、全体のデータ整合性が崩れ去っている……。これが、実務で最も恐ろしい「サイレントエラー」の正体です。

2. 救世主 `dbFailOnError` の正体と仕組み

この恐怖の「サイレントエラー」を撃退し、データベースの秩序を守る騎士こそが、今回テーマにする `dbFailOnError` オプションです。

使い方は極めてシンプル。`Execute` メソッドの第2引数に、この定数をポンと追加するだけです。

CurrentDb.Execute “UPDATE T_受注台帳 SET ステータス = ‘完了’ WHERE 注文ID = 9999”, dbFailOnError

たったこれだけ?と思われるかもしれませんが、効果は絶大です。
このオプションを付与すると、DAOは次のような挙動に変わります。

1. トランザクションの保護: SQLの実行中に1件でもエラーが発生した場合、その実行は即座に中断されます。
2. ロールバックの保証: 途中で失敗した場合、そのSQL文で行われた変更は「なかったこと(元の状態)」に自動的に巻き戻されます。中途半端なデータが残ることは絶対にありません。
3. エラーの発生: VBA側で実行時エラー(トラップ可能なエラー)が発生するため、`Err` オブジェクトで確実に検知できます。

3. 実践!安全なトランザクション制御コード

それでは、実際の開発現場でそのままコピペして使える、堅牢(ロバスト)なエラーハンドリング付きのコードパターンを見てみましょう。

Sub UpdateOrderStatusSafe()
On Error GoTo ErrorHandler ‘ エラー発生時のジャンプ先を指定

Dim strSQL As String
strSQL = “UPDATE T_受注台帳 SET ステータス = ‘完了’ WHERE 処理フラグ = 0”

‘ dbFailOnError を付与して実行
CurrentDb.Execute strSQL, dbFailOnError

MsgBox “データの更新が正常に完了しました!”, vbInformation, “成功”
Exit Sub

ErrorHandler:
‘ 万が一エラーが発生した場合の処理
MsgBox “データの更新に失敗しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “致命的エラー”

‘ ここでログ出力や追加のロールバック処理を行うことも可能
End Sub

このコードの美しいポイント

  • データの不整合を防ぐ: もし1000件のデータを更新する途中で999件目でエラーが起きても、1件目から998件目までの変更が勝手に保存されてしまうことはありません。すべてが安全にロールバックされます。
  • ユーザーへの親切なフィードバック: 「何が起きたのか分からない」という最悪の状況を回避し、エラー内容を正確にユーザー(または自分自身)に伝えることができます。

4. チーフアーキテクトからの実践アドバイス

最後に、より高度な開発を目指すあなたへ、ワンランク上の知見を授けます。

`CurrentDb.Execute` は非常に強力ですが、もし「複数の異なるテーブルに対して、一連のINSERTやUPDATEをセットで行い、どれか一つでも失敗したら全体をキャンセルしたい」という場合は、`CurrentDb.Execute` 単体では不十分です。

その場合は、次のように `Workspace` オブジェクトを使った本格的なトランザクション(BeginTrans / CommitTrans / Rollback)と `dbFailOnError` を組み合わせるのが、Access開発の最高峰のテクニックとなります。

Sub AdvancedTransactionSample()
Dim ws As DAO.Workspace
Set ws = DBEngine.Workspaces(0)

On Error GoTo TransactionError

‘ トランザクション開始
ws.BeginTrans

‘ 1つ目の処理
ws.Databases(0).Execute “UPDATE T_在庫 先生… (省略)”, dbFailOnError

‘ 2つ目の処理
ws.Databases(0).Execute “INSERT INTO T_履歴 … (省略)”, dbFailOnError

‘ すべて成功したらコミット(確定)
ws.CommitTrans
MsgBox “全トランザクションが成功しました。”, vbInformation
Exit Sub

TransactionError:
‘ 失敗したらロールバック(全取り消し)
ws.Rollback
MsgBox “エラーが発生したため、すべての変更をキャンセルしました。” & vbCrLf & Err.Description, vbCritical
End Sub

まとめ

  • `CurrentDb.Execute` を使うときは、必ず `dbFailOnError` をセットで書く ことをコーディングの習慣にしましょう。
  • デフォルトのままだと、エラーが起きてもデータが中途半端に壊れる「サイレントエラー」の罠にハマります。
  • しっかりとエラーを検知し、データベースの健全性を保つプログラミングを身につければ、あなたの作るAccessアプリの信頼性は劇的に向上します。

基本をマスターした今、あなたはもう「マクロの記録者」ではありません立派な「Access VBAエンジニア」です。ぜひ、今日からのコードに取り入れてみてくださいね!

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