こんにちは!データベースの設計やAccess VBAのカスタマイズ、日々の業務でお疲れ様です。
マクロの記録から一歩踏み出し、「自分でプログラムを書いて業務を自動化したい!」と思えるようになった頃、多くの人がぶ
つかる壁があります。それが「テーブル同士のリレーションシップ(関係性)の管理」です。
例えば、親データ(顧客)を削除したときに、子データ(注文履歴)が宙ぶらりんになって残ってしまう……。これを防ぐために「連鎖削除(カスケードデリート)」の設定が必要ですが、テーブルが数十個もある巨大なシステムで、これをGUI(画面のポチポチ操作)で一つずつ設定するのは、気の遠くなる作業ですし、設定漏れというヒューマンエラーの温床になります。
今回は、そんな絶望的な手作業からあなたを解放する、「リレーションシップの連鎖削除設定をVBAで一括制御する極意」を伝授します。ここをクリアすれば、Access VBAを使ったデータベースの構造制御はもう怖くありません。一緒にバッチリマスターしていきましょう!
—
なぜVBAでリレーションシップを制御するのか?
GUIでリレーションシップを設定する場合、次のようなデメリットがあります。
1. テーブルを開いているとエラーになる:デザインビューなどでテーブルを開いたままだと設定できない。
2. 変更の履歴が残らない:後から「誰が・どのテーブルに・どんな設定をしたか」がブラックボックス化する。
3. 大量処理に向かない:テーブルが50個、100個と増えたときに手作業では破綻する。
VBAを使えば、これらを一瞬で、プログラムのコードという「設計図」の形で再現できます。何度やり直しても同じ結果になる「再現性」と「確実性」を手に入れることができるのです。
—
リレーションシップ制御の全体像と仕組み
Accessでリレーションシップ(VBAの世界では `Relation` オブジェクトと呼びます)をプログラムから操作するには、DAO(Data Access Objects)というデータベース操作のエンジンを使います。
まずは、リレーションシップの基本的な構造を押さえましょう。
- 親テーブル(主側):例「T_顧客」
- 子テーブル(従側):例「T_注文」
- 結合キー:例「顧客ID」
- 整合性ルール:
- 「参照整合性の強制」(存在しない親を参照させない)
- 「連鎖更新」(親のIDが変わったら子も追従する)
- 「連鎖削除」(親を消したら子も一緒に消す)
これらをVBAでコード化すると、驚くほどシンプルに記述できます。
—
【実践】連鎖削除を一括設定するVBAコード
それでは、開発の現場でそのままコピペして使える実用的なコードをご紹介します。
このコードは、「指定した親テーブルと子テーブルの間に、参照整合性と連鎖削除(カスケードデリート)を持ったリレーションシップを自動作成する」プロシージャです。すでにリレーションが存在する場合は、一度削除して安全に再作成するロジック(イデポテンシー:何度実行しても安全な性質)を組み込んでいます。
Sub CreateCascadeRelationExample()
Dim db As DAO.Database
Dim rel As DAO.Relation
Dim fld As DAO.Field
‘ 定数定義(実際のテーブル名・フィールド名に合わせて変更してください)
Const TARGET_REL_NAME = “FK_Customer_Order” ‘ リレーション名
Const PK_TABLE = “T_顧客” ‘ 親テーブル
Const FK_TABLE = “T_注文” ‘ 子テーブル
Const JOIN_FIELD = “顧客ID” ‘ 結合するフィールド名
‘ 現在のデータベースオブジェクトを取得
Set db = CurrentDb
On Error GoTo ErrorHandler
‘ 1. すでに同名のリレーションが存在する場合は、あらかじめ削除する
‘ (エラーハンドリングを使わず、Errorsコレクションを走査する方法もありますが今回はシンプルに)
Dim i As Integer
For i = db.Relations.Count – 1 To 0 Step -1
If db.Relations(i).Name = TARGET_REL_NAME Then
db.Relations.Delete TARGET_REL_NAME
Exit For
End If
Next i
‘ 2. 新しいリレーションオブジェクトを作成する
Set rel = db.CreateRelation(TARGET_REL_NAME, PK_TABLE, FK_TABLE)
‘ 3. リレーションをむすぶ「フィールド」を追加する
‘ CreateField(フィールド名) として親側のフィールドを指定し、ForeignNameに子側のフィールドを設定する
Set fld = rel.CreateField(JOIN_FIELD)
fld.ForeignName = JOIN_FIELD
rel.Fields.Append fld
‘ 4. 各種フラグ(整合性・連鎖削除など)を設定する
‘ dbEnforceIntegrity : 参照整合性を強制する
rel.Attributes = dbEnforceIntegrity + dbCascadeDelete
‘ 5. データベースにリレーションを登録する
db.Relations.Append rel
MsgBox “リレーションシップと連鎖削除の設定が完了しました!”, vbInformation, “成功”
CleanUp:
‘ オブジェクトの解放(メモリリークを防ぐプロの作法です)
Set fld = Nothing
Set rel = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
コードの重要ポイント解説
1. `db.CreateRelation`
親と子を繋ぐ「関係そのもの」をメモリ上に生み出します。この時点ではまだデータベースには保存されていません。
2. `fld.ForeignName = JOIN_FIELD`
親テーブルと子テーブルのフィールド名が同じ場合はこの記述でOKです。もし子側のフィールド名が違う場合でも、ここに別名を設定すれば対応可能です。
3. `rel.Attributes = dbEnforceIntegrity + dbCascadeDelete`
ここが今回のキモです!
- `dbEnforceIntegrity` で「参照整合性」をONにし、
- `+ dbCascadeDelete` で「連鎖削除」を有効化しています。
もし連鎖更新も入れたい場合は、さらに `+ dbCascadeUpdate` を足すことで複合的に設定できます。
—
陥りやすい罠とエラー回避の極意
VBAでリレーションシップを操作するとき、初学者が必ずと言っていいほどハマる「3つの罠」があります。ここを知っておくだけで、無駄なデバッグ時間を何時間も節約できます。
罠その1:テーブルが開いている
- 症状:`実行時エラー ‘3008’: テーブル ‘T_顧客’ は排他使用のためロックされています。`
- 対策:VBAを実行する前に、対象となるテーブルやクエリ、フォームはすべて閉じておきましょう。プログラムから強制的に閉じることはDAOでは難しいため、「実行前にはすべてのウィンドウを閉じる」運用ルールにするのが確実です。
罠その2:すでにゴミデータ(不整合データ)が存在している
- 症状:コードの書き方は正しいのに、`実行時エラー ‘3216’: フィールドの定義が不正です` や整合性エラーが出る。
- 対策:子テーブル(T_注文)側に、親テーブル(T_顧客)に存在しない「孤児レコード(ゾンビデータ)」がすでに含まれている場合、Accessは参照整合性の強制を拒絶します。必ず事前に不整合なデータをクエリ等でクレンジング(削除または修正)してからコードを実行してください。
罠その3:データ型が完全一致していない
- 症状:結合しようとしているフィールド同士の型が違う(例:親が「長整数型(Long)」、子が「テキスト型(Short Text)」)。
- 対策:リレーションシップを結ぶ両者のフィールドの「データ型」と「フィールドサイズ」は完全に一致していなければなりません。設計段階でのミスを防ぐためにも、テーブル定義自体もVBA(TableDefオブジェクト)で一括制御できるようになると、さらに強固なシステムが作れます。
—
まとめ
いかがでしたでしょうか?
今回は、少しハードルが高く見える「リレーションシップの連鎖削除設定のVBA一括制御」について解説しました。
- GUIでの手作業から脱却し、`CreateRelation` と `Attributes` を使いこなすことで、プログラムから一撃で整合性を担保できること。
- 実行前にはテーブルを閉じ、ゴミデータをなくしておくという「実務上の鉄則」があること。
これらを理解できたあなたは、もう「マクロの記録をポチポチ押すだけの初学者」ではありません。立派なデータベース・アーキテクトの第一歩を踏み出しています。
大規模なAccess開発の現場でも、この手法を知っていれば設計変更のたびに冷や汗をかく必要はなくなります。ぜひ、ご自身の開発環境やテスト環境で試してみてくださいね。
あなたのAccessライフが、よりスマートで快適なものになりますように!それでは、また次の極意でお会いしましょう。
