【テクニカル・上級編】【上級】テーブル定義変更時の「トランザクション制御」:失敗時にロールバックする仕組み – Access VBA解析バイブル

スポンサーリンク

テーブル定義変更の「不可逆性」を制する:DAOトランザクションの深淵と設計哲学

Accessでシステムを構築する際、誰もが一度は直面する壁がある。それは「テーブル定義の変更(DDL操作)」が、通常のデータ操作(DML)とは全く異なる「重さ」と「不可逆性」を持っているという事実だ。

特に、配布済みのフロントエンドからバックエンドのテーブル構造を動的に書き換える際、エラーで処理が中断すればどうなるか。半端な状態で残されたメタデータは、システムを「死」へと導く。

今日は、DAOのトランザクション制御を駆使し、テーブル定義変更を「アトミック(不可分)」な操作へと昇華させる極限の手法を伝授する。

—

1. DDLとトランザクションの「残酷な真実」

Accessにおいて、`TableDef`や`Field`オブジェクトの操作は、`DBEngine.BeginTrans`で保護できる場合と、そうでない場合がある。

実は、AccessのDAOトランザクションは、データ操作に対しては完璧だが、DDL(テーブル作成・変更・削除)に対しては、ACEエンジンが裏で暗黙のコミット(Auto-Commit)を発生させるケースがあることを忘れてはならない。

したがって、物理的な構造変更を行う際は、単にトランザクションで囲むだけでなく、「予備のテーブル(またはフィールド)を操作し、最後に名前を入れ替える」という、いわゆる「スワップ・プロトコル」こそが、シニアエンジニアの嗜みである。

—

2. 実装:構造変更の安全なアトミック・スワップ

以下のコードは、テーブル変更の失敗を許さないための堅牢なテンプレートだ。

‘ 伝説的な堅牢性を実現するテーブル変更プロシージャ
Public Sub SafeModifyTableStructure()
Dim db As DAO.Database
Dim td As DAO.TableDef
Dim ws As DAO.Workspace

Set ws = DBEngine.Workspaces(0)
Set db = CurrentDb

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

On Error GoTo Rollback_Handler

‘ 1. バックアップの作成 (物理的なコピー)
‘ 構造変更対象のテーブルを一時的に退避
DoCmd.CopyObject , “T_Target_Backup”, acTable, “T_Target”

‘ 2. 構造の変更を実行
Set td = db.TableDefs(“T_Target”)
Dim fld As DAO.Field
Set fld = td.CreateField(“NewColumn”, dbText, 255)
td.Fields.Append fld

‘ 3. ここで意図的なエラーを発生させてテストするのも良い

‘ 全て成功すればコミット
ws.CommitTrans

‘ 後処理:バックアップ削除
DoCmd.DeleteObject acTable, “T_Target_Backup”

CleanUp:
Set fld = Nothing
Set td = Nothing
Set db = Nothing
Exit Sub

Rollback_Handler:
‘ 失敗時はすべてを無に帰す
ws.Rollback
MsgBox “構造変更に失敗しました。ロールバックを実行します。”, vbCritical
Resume CleanUp
End Sub

—

3. シニアエンジニアが守るべき3つの鉄則

① オブジェクトの明示的解放(Memory Lifecycle)

VBAはガベージコレクションが脆弱だ。`TableDef`や`Field`を操作した直後に `Set object = Nothing` を怠ると、ACEエンジンがロックを保持し続け、ネットワーク共有環境下で「ファイルが使用中です」という悪夢を引き起こす。常に参照を切り離せ。

② Windows APIによる排他制御(Mutex)

もしバックエンドが共有フォルダにある場合、DAOのロックだけでは不十分なことがある。`OpenProcess`や`CreateMutex` APIを用いて、更新処理中であることをシステムレベルでフラグ立てし、他のインスタンスからの書き込みを物理的に遮断するのが、大規模システムでは定石である。

③ インデックスの再構築というコスト

テーブル定義を変更する際、既存のインデックスやリレーションシップ(`Relation`オブジェクト)は一度破棄されるリスクがある。

  • 知見: 構造変更前に、`db.Relations`コレクションを走査し、リレーションの定義を自前で配列やコレクションに退避させておくこと。構造変更完了後に、その退避した定義を再構築するスクリプトを走らせるのが、真のプロフェッショナルの仕事だ。

—

最後に:レガシーを「レガシー」で終わらせないために

Accessは「古い」のではない。単に「使い方が難しい」だけだ。
テーブル定義をVBAで制御するということは、アプリケーションの「骨格」を動的に変えるという外科手術に近い行為である。

今回紹介したトランザクションとバックアップによる二重の安全網を張り、さらにエラーログの書き出しを徹底すれば、Accessシステムは堅牢なサーバーサイド・アプリケーションに匹敵する安定性を手に入れる。

君が書いたコードが、10年後の担当者に「なぜこんなに安定しているのか?」と驚かれるような、そんなアーキテクチャを追求してほしい。技術は嘘をつかない。ただ、正しく実装された者にのみ微笑むのだ。

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