【Access VBA】神は細部に宿る:テーブル変更監視システムによる「見えないバグ」の撲滅
Accessの現場で最も恐ろしいのは、「誰がいつの間にかテーブル定義を変えたかわからない」という事態だ。フィールドの型変更や削除、インデックスの欠落が、既存のクエリやフォームを静かに腐らせていく。
多くの開発者は「運用ルール」でこれを防ごうとするが、ルールは破られるためにある。システムで物理的に検知する。それがプロフェッショナルの矜持だ。今回は、`TableDef`を掌握し、変更を即座に通知する「監視アーキテクチャ」を伝授する。
—
1. なぜ「LastUpdated」だけでは不十分なのか
初心者は `TableDef.LastUpdated` を見るだけで満足する。だが、これは罠だ。このプロパティは、データの中身の更新やインデックス変更でも書き換わることがある。
真に監視すべきは、「DAOレベルでのスキーマの完全な一致」だ。
以下の設計思想で構築する。
- 完全比較: フィールド名、型、サイズ、属性をハッシュ化(あるいは文字列結合)し、前回のスナップショットと比較する。
- 堅牢な永続化: 比較対象となる「正」のデータは、外部の隠しテーブル、あるいはローカルの外部設定ファイルに保存する。
- 疎結合な通知: 通知ロジックを分離し、将来的にSlackやTeamsのWebhookへ移行できるように設計する。
—
2. 実装:変更検知エンジンの設計
以下のコードは、テーブルの構成情報を文字列として抽出し、前回値と比較する核となるロジックだ。
‘ ———————————————————————-
‘ テーブル定義の「指紋」を生成する関数
‘ ———————————————————————-
Private Function GetTableSchemaFingerprint(tableName As String) As String
Dim db As DAO.Database: Set db = CurrentDb
Dim td As DAO.TableDef
Dim fld As DAO.Field
Dim schemaInfo As String
Set td = db.TableDefs(tableName)
‘ システムテーブルは除外する(重要)
If (td.Attributes And dbSystemObject) = 0 Then
For Each fld In td.Fields
‘ フィールド名|型|サイズ を連結して一意のIDとする
schemaInfo = schemaInfo & fld.Name & “:” & fld.Type & “:” & fld.Size & “;”
Next fld
End If
GetTableSchemaFingerprint = schemaInfo
End Function
—
3. 変更を検知し通知するプロダクションコード
このツールは、起動時に「前回のスナップショット」と「現在の状態」を比較する。差分があれば即座にメールを飛ばす。
Public Sub MonitorTableSchema()
Dim db As DAO.Database: Set db = CurrentDb
Dim td As DAO.TableDef
Dim currentFingerprint As String
Dim storedFingerprint As String
‘ 実際の実装では、このSQLで取得するテーブルは設定ファイル等から読み込む
For Each td In db.TableDefs
If (td.Attributes And dbSystemObject) = 0 Then
currentFingerprint = GetTableSchemaFingerprint(td.Name)
storedFingerprint = DLookup(“Fingerprint”, “tbl_SchemaSnapshot”, “TableName = ‘” & td.Name & “‘”)
‘ 差分がある場合、または新規テーブルの場合
If currentFingerprint <> storedFingerprint Then
Call SendAlertEmail(td.Name)
‘ 更新日を記録し、次回比較に備える(更新クエリを実行)
Call UpdateSnapshot(td.Name, currentFingerprint)
End If
End If
Next td
End Sub
Private Sub SendAlertEmail(tableName As String)
‘ CDO等を利用してSMTP直叩きを推奨。Outlookオブジェクトは不安定なため避ける
Debug.Print “【警告】テーブル変更検知: ” & tableName
‘ ここにメール送信ロジックを実装
End Sub
—
4. プロの視点:開発上の注意点
このツールを導入する際、以下の3点を必ず守れ。
1. システムテーブルの除外: `dbSystemObject` 属性をチェックしないコードは、Access自身の内部動作で誤作動を起こす。これは鉄則だ。
2. パフォーマンスへの配慮: フィールド数が多いテーブルを毎秒比較するのは愚策だ。このチェックは「アプリケーション起動時」または「管理者メニューから手動実行」のみに行う設計にせよ。
3. スナップショットの保護: 比較用テーブル `tbl_SchemaSnapshot` は、一般ユーザーが触れないように隠しオブジェクト属性を設定し、フロントエンドではなく、可能であればバックエンド(共有フォルダ上のmdb/accdb)に置くのが理想だ。
—
最後に:ツールは「文化」を作る
このツールを導入したからといって、変更がなくなるわけではない。しかし、「誰が変更したか」「いつ変更されたか」が可視化されるという事実が、開発チームに規律をもたらす。
「なぜ動かないのか」という終わりのないデバッグに時間を浪費するのはもう終わりにしよう。システムを監視し、異常を早期に検知する。それこそが、凡百のAccess職人から脱却し、真のエンジニアへと至るための第一歩だ。
コードを書き換える準備はできたか?現場の静かなる腐敗を、今すぐ食い止めろ。
