Access VBAを掌握せよ:リレーションシップをコードで「支配」する極限の技術
現場のAccess開発において、リレーションシップの設定をGUIでポチポチと設定しているようでは、プロフェッショナルとは言えない。
要件が頻繁に変わる業務アプリにおいて、テーブル構造の変化を「手動」で追従させるのは、バグを製造しているのと同じだ。我々アーキテクトは、データベースの整合性すらもコードの管理下に置く。
今日は、`Relation`オブジェクトを使いこなし、テーブル間の結合を動的に制御する「堅牢な設計」の極意を伝授する。
—
1. なぜ「動的制御」が必要なのか
初心者は「GUIで設定すれば終わり」と考えがちだ。しかし、実務では以下のようなシナリオが頻発する。
- 一時テーブルとの動的結合: インポートした外部データに対し、実行時に整合性を担保したい。
- 構造の自動再構築: バージョンアップ時に、特定の業務ロジックに合わせてリレーションを張り直す必要がある。
- 整合性の強制削除: テストデータの投入前後に、リレーションを動的に解除し、自由なデータ操作を保証する。
これらをGUIに依存させると、運用担当者が設定をミスするリスクが100%発生する。「コードがすべて」であるべきだ。
—
2. 破壊的な失敗を避けるための「設計の鉄則」
`Relation`オブジェクトを触る際、以下の3点を遵守しない者は、確実にDBを破壊する。
1. 存在チェックの徹底: `Relations`コレクションに同名のオブジェクトが存在するか確認し、あれば削除してから生成する。これを怠ると「オブジェクトは既に存在します」エラーで止まる。
2. 属性(Attributes)の理解: 単に結合するだけでなく、連鎖削除(Cascade Delete)や連鎖更新(Cascade Update)をどう扱うか。ここを理解せずデフォルトのまま使うのは無謀だ。
3. エラーハンドリング: リレーション設定は、データに矛盾がある場合(親に存在しない子が既に存在する等)に即座に失敗する。必ずトラップせよ。
—
3. 実践:保守性の高いプロダクションコード
以下は、安全かつ再利用可能な「リレーション設定関数」のテンプレートだ。これをモジュールに格納し、プロジェクトの標準ツールとして活用せよ。
‘ —————————————————————————
‘ 関数名:CreateRelationSafe
‘ 概要:リレーションを安全に作成し、既に存在する場合は再構築する
‘ —————————————————————————
Public Function CreateRelationSafe(strRelName As String, _
strPrimaryTable As String, _
strForeignTable As String, _
strPrimaryField As String, _
strForeignField As String) As Boolean
Dim db As DAO.Database
Dim rel As DAO.Relation
Dim fld As DAO.Field
On Error GoTo ErrorHandler
Set db = CurrentDb
‘ 1. 同名リレーションが存在する場合は削除(再構築の基本)
On Error Resume Next
db.Relations.Delete strRelName
On Error GoTo ErrorHandler
‘ 2. Relationオブジェクトの作成
Set rel = db.CreateRelation(strRelName, strPrimaryTable, strForeignTable)
‘ 3. 属性の設定(連鎖更新・削除を有効にする場合)
‘ dbRelationUpdateCascade + dbRelationDeleteCascade を指定
rel.Attributes = dbRelationUpdateCascade + dbRelationDeleteCascade
‘ 4. フィールドの紐付け
Set fld = rel.CreateField(strPrimaryField)
fld.ForeignName = strForeignField
rel.Fields.Append fld
‘ 5. コレクションに追加して確定
db.Relations.Append rel
CreateRelationSafe = True
Exit Function
ErrorHandler:
Debug.Print “Error: ” & Err.Number & ” – ” & Err.Description
CreateRelationSafe = False
End Function
このコードの「設計意図」
- `On Error Resume Next`の活用: 削除時に「存在しない」というエラーが出るのは正常な動作なので、意図的に無視している。
- 疎結合な設計: 引数をテーブル名とフィールド名に限定することで、特定の業務ロジックに依存せず、あらゆるテーブル間で使用可能にしている。
- 属性の明示: `dbRelationUpdateCascade`などの定数を使うことで、後からコードを見た人間が「なぜこの設定にしたのか」を即座に理解できるようにしている。
—
4. 最後に:エンジニアとしてのマインドセット
リレーションを動的に制御する技術は、あなたのアプリケーションを「単なる道具」から「自己管理能力を持ったシステム」へと昇華させる。
ただし、過剰な動的生成はコードの複雑性を高める。「静的に定義できるものは静的に、動的な変更が必要なものだけをコードで扱う」。このバランス感覚こそが、真に優秀なエンジニアの証だ。
次は、この技術を応用して、データインポート処理と連携させた「自動整合性検証エンジン」の構築に挑戦してみるといい。Accessの限界を突破するのは、いつだってGUIではない。あなたの書く、その数行のコードだ。
