こんにちは!Access VBAの奥深い世界へようこそ。
今回は、現場でシステムを安定稼働させるために避けて通れない、「テーブル定義の変更履歴を自動記録する仕組み(監査ログ)」についてお話しします。
「マクロの記録」から一歩抜け出し、本格的なシステム開発を目指すあなたにとって、データベースの構造(スキーマ)がいつ、誰によって変更されたかを追跡することは、プロとしての必須スキルです。
今回は、Accessの裏側で何が起きているのかという本質に迫りながら、実務でそのまま使えるコードを一緒に紐解いていきましょう。ここをクリアすれば、あなたのAccess開発のレベルは一段も二段も跳ね上がりますよ。バッチリ解説していきますね!
—
1. なぜAccessに「監査ログ」が必要なのか?
実務でAccessデータベースを運用していると、こんな恐怖体験をしたことはありませんか?
- 「昨日まで動いていた集計クエリが、急にエラーになった…」
- 「フィールドの名前が勝手に変わってる!誰がやったの!?」
- 「テーブルのデータ型が変更されて、VBAのインポート処理が爆発した!」
Access(Jet/ACEエンジン)は非常に手軽で強力な反面、複数人で共有していると「いつの間にか誰かがテーブル設計を変えてしまった」という事故が起こりがちです。
SQL Serverなどの本格的なRDBにはトリガー機能がありますが、Accessには「テーブル定義の変更(DDL)を直接フックする自動トリガー機能」が標準ではありません。
では、どうするか? Accessの「内部イベント」や「オブジェクトの走査」をVBAで制御し、擬似的に変更検知システムを構築するのです。
—
2. 全体像:どうやってテーブル定義の変更を検知するのか?
今回は、以下のアプローチで監査システムを構築します。
1. 監査ログ用テーブルの準備: 「いつ、どのテーブルの、どのフィールドが、どう変わったか」を記録する場所を作ります。
2. 現在のテーブル定義のスナップショット保持: 起動時や定期的に、現在の `TableDef`(テーブル定義)の情報をメモリ(または一時テーブル)に保持します。
3. 差分検出ロジック(VBA): 最新の定義と過去の定義を比較し、変更があれば自動でログテーブルに書き込みます。
今回は、実務で最も需要が高い「フィールドの追加・削除・データ型変更」を検知するエンジンを作ってみましょう。
—
3. 実装ステップ
ステップ1:監査ログを保存するテーブルを作る
まずは、変更履歴を書き留めておく「お巡りさん」の席を用意します。
Accessのテーブルビュー、またはVBAで以下のテーブル(名前:`z_Tbl_AuditLog`)を作成してください。
- LogID(オートナンバー / 主キー)
- ChangeDate(日付/時刻)- 変更日時
- UserName(短テキスト)- 変更したユーザー名
- ObjectName(短テキスト)- 対象のテーブル名
- ChangeType(短テキスト)- 変更の種類(追加 / 削除 / 型変更 など)
- Detail(長テキスト)- 詳細情報
—
ステップ2:変更検知と記録を行うVBAコード
ここからが本番です。
VBAの標準モジュールに、以下のコードを記述してください。ここでは、特定の重要テーブルのフィールド構成をチェックし、前回との差分を検出してログに残すプロシージャを実装します。
Option Compare Database
Option Explicit
‘ =====================================================================
‘ 目的: 指定したテーブルのフィールド定義を検査し、変更があればログに残す
‘ 著者: チーフアーキテクト
‘ =====================================================================
Public Sub CheckTableDefinitionChanges(ByVal targetTableName As String)
On Error GoTo ErrorHandler
Dim db As DAO.Database
Dim tdef As DAO.TableDef
Dim fld As DAO.Field
Set db = CurrentDb
‘ 対象テーブルが存在するかチェック
If Not TableExists(db, targetTableName) Then
MsgBox “指定されたテーブルが見つかりません: ” & targetTableName, vbExclamation
Exit Sub
End If
Set tdef = db.TableDefs(targetTableName)
‘ 【重要】本来は前回の定義を保持したメタデータテーブルと比較しますが、
‘ 今回は「現在のフィールド一覧をイミディエイトウィンドウに出力し、
‘ 監査ログテーブルに記録する基本形」を示します。
Dim logDetail As String
logDetail = “テーブル [” & targetTableName & “] の構造スナップショット取得”
‘ ログテーブルへの書き込み処理を呼び出し
Call WriteAuditLog(targetTableName, “SCHEMA_CHECK”, logDetail)
MsgBox “テーブル [” & targetTableName & “] の監査チェックが完了しました。”, vbInformation, “確認”
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ ———————————————————————
‘ 補助関数: 監査ログテーブルへレコードを挿入する
‘ ———————————————————————
Private Sub WriteAuditLog(ByVal objName As String, ByVal changeType As String, ByVal detail As String)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset(“z_Tbl_AuditLog”, dbOpenDynaset)
rs.AddNew
rs!ChangeDate = Now()
rs!UserName = Environ$(“UserName”) ‘ Windowsのログインユーザー名を取得
rs!ObjectName = objName
rs!ChangeType = changeType
rs!Detail = detail
rs.Update
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
‘ ———————————————————————
‘ 補助関数: テーブルの存在確認
‘ ———————————————————————
Private Function TableExists(db As DAO.Database, tableName As String) As Boolean
Dim tdf As DAO.TableDef
TableExists = False
For Each tdf In db.TableDefs
If tdf.Name = tableName Then
TableExists = True
Exit For
End If
Next tdf
End Function
コードのポイント解説
1. `Environ$(“UserName”)`: Windowsのログインユーザー名を取得しています。「誰がこの変更を加えたのか」を特定するために、監査ログには絶対に欠かせない要素です。
2. `DAO.TableDef` と `DAO.Field`: Accessのデータベース構造をプログラムから操作・参照するためのオブジェクトです。これらを使いこなすことで、フォームからではなくVBAのコードベースでテーブルの全貌を把握できます。
3. エラーハンドリング (`On Error GoTo`): データベース操作は予期せぬ排他制御エラーやオブジェクト不在エラーが起きやすいため、本番コードでは必ずエラーフックを仕込みましょう。
—
4. 陥りやすい罠とプロの知見
実務でこの仕組みを運用しようとすると、いくつかの「壁」にぶつかります。先輩からのアドバイスとして、あらかじめ共有しておきますね。
罠1:「デザインビューでの手動変更」はVBAで直接キャッチできない
Accessの画面上でユーザーがパパッとフィールドを追加した瞬間、それをリアルタイムでVBAが割り込んで検知することは、標準のAccess機能では困難です。
【解決策のヒント】
本格的なシステムにする場合は、「データベース起動時(AutoexecマクロやメインフォームのOpenイベント)」に上記のチェック処理を走らせるか、テーブル定義を変更する専用の「管理用フォーム」を用意し、そこを経由して変更させます(直接テーブルを開かせないセキュリティ設定を行う)。
罠2: ログテーブル自体が肥大化する
運用が長くなると、監査ログのレコード数が数万件を超え、データベース全体のパフォーマンス低下を招きます。
【解決策のヒント】
定期的に古いログ(例:1年以上前)を別アーカイブへ退避させる、あるいは削除するメンテナンスバッチをVBAで組んでおくのがプロの作法です。
—
まとめ
今回は、Access VBAを使ったテーブル定義の監査ログ設計の基本について解説しました。
- 監査ログテーブルを用意して「誰が・いつ・何をしたか」を残す基盤を作る。
- DAOオブジェクト(TableDef / Field)を駆使してデータベースの構造をプログラムから監視する。
- 変更の検知タイミングを工夫し、システム運用の安全性を高める。
「動けばいいや」というコードから、「堅牢でメンテナンス性の高いシステム」へステップアップするための第一歩として、ぜひご自身の環境でも試してみてくださいね。
ここをクリアすれば、Access VBAの基本はバッチリですよ!次のステップでも、さらに実務で役立つ知見をお届けしていきます。お楽しみに!
