大規模テーブル分割の流儀:Access VBAで「データ再構築」を自動化する極限技術
Accessでシステムを運用していると、避けて通れないのが「初期設計の破綻」だ。Excelライクなフラットテーブルが数万レコードを超え、クエリが重くなり、整合性が崩壊したその時、君は「データ構造の再設計」を突きつけられる。
手作業でのコピペやインポートなど論外だ。それは人為的ミスを生む温床であり、エンジニアの仕事ではない。今回は、DAO(Data Access Objects)を駆使し、フラットなテーブルを正規化されたリレーショナル構造へ自動変換する、プロフェッショナルな移行スクリプトの設計手法を伝授する。
—
1. 設計の根幹:なぜ「一括処理」が必要なのか
大規模なデータ移行において、最も恐れるべきは「中途半端な状態でのエラー停止」だ。
トランザクションを張らず、インデックスを後回しにし、リレーションを考慮しない設計は、現場のエンジニアを地獄へ引きずり込む。
我々が守るべき設計指針は以下の3点だ。
- Atomic(原子性): 移行プロセスを「抽出・加工・書き込み」の最小単位に分割する。
- Idempotency(冪等性): 何度実行しても結果が同じになる(実行前のクリーンアップが必須)。
- Metadata-Driven: 物理テーブル名をハードコードせず、マッピング定義をテーブル管理する。
—
2. 実装:正規化自動移行エンジン
以下のコードは、単なるコピペコードではない。DAOの `TableDefs` と `CreateRelation` を駆使し、スキーマレベルでの再構築を自動化するアーキテクチャだ。
Option Compare Database
Option Explicit
‘ 大規模データ分割・移行のメインエンジン
Public Sub ExecuteSchemaMigration()
On Error GoTo ErrorHandler
Dim db As DAO.Database
Set db = CurrentDb
‘ 1. データベースの整合性を確保するためのトランザクション開始
DBEngine.BeginTrans
‘ 2. 既存の移行先テーブルをクリーンアップ(冪等性の担保)
ClearMigrationTables db
‘ 3. 正規化処理:フラットな[SourceTable]から[MasterTable]と[DetailTable]を生成
‘ 擬似コード的な実装例
db.Execute “INSERT INTO tbl_Master (KeyID, Name) SELECT DISTINCT KeyID, Name FROM SourceTable”, dbFailOnError
db.Execute “INSERT INTO tbl_Detail (KeyID, Value, Date) SELECT KeyID, Value, Date FROM SourceTable”, dbFailOnError
‘ 4. リレーションシップの再構築
CreateRelationship db, “tbl_Master”, “tbl_Detail”, “KeyID”
DBEngine.CommitTrans
MsgBox “移行完了:データ整合性は保たれています。”, vbInformation
Exit Sub
ErrorHandler:
DBEngine.Rollback
MsgBox “致命的なエラー:” & Err.Description, vbCritical
End Sub
‘ リレーションシップ構築の職人芸
Private Sub CreateRelationship(db As DAO.Database, pkTable As String, fkTable As String, fieldName As String)
Dim rel As DAO.Relation
‘ 既存リレーションの削除(重複回避)
On Error Resume Next
db.Relations.Delete “Rel_” & pkTable & “_” & fkTable
On Error GoTo 0
‘ リレーションオブジェクトの生成と設定
Set rel = db.CreateRelation(“Rel_” & pkTable & “_” & fkTable, pkTable, fkTable, dbRelationUpdateCascade + dbRelationDeleteCascade)
rel.Fields.Append rel.CreateField(fieldName)
rel.Fields(0).ForeignName = fieldName
db.Relations.Append rel
End Sub
—
3. 現場で生き残るための「3つの鉄則」
① インデックスは「移行後」に貼れ
大量データを挿入する際、インデックスが既に存在していると、挿入のたびにB-Treeの再構築が発生し、パフォーマンスが劇的に低下する。「テーブル作成 → データ転送 → インデックス構築」の順序を徹底せよ。
② DAOの `dbFailOnError` を使いこなせ
`DoCmd.RunSQL` を使って警告ダイアログに振り回されるのは素人だ。`db.Execute` に `dbFailOnError` を付与することで、SQL実行時にエラーが発生した際、即座にトラップ可能になる。これが堅牢な自動化の第一歩だ。
③ リレーション削除の「お作法」
`db.Relations.Delete` は、存在しない名前を指定するとエラーを吐く。必ず `On Error Resume Next` で囲むか、事前に `For Each` ループでコレクション内に存在するかを確認するガード節を設けること。
—
結論:技術は「仕組み」に落とし込むもの
VBAは、単なる「便利な機能」ではない。君が構築したこの移行スクリプトは、将来的にテーブル定義が変わった際にも、定義テーブルを書き換えるだけで対応できる「資産」となる。
コードを書き捨てるな。再利用性を設計し、堅牢性を担保せよ。
それが、Accessという老練なプラットフォームを掌握し、業務自動化の頂点へ至るための唯一の道だ。
次のステップとして、このスクリプトを「ログ記録機能付きのライブラリ」へと昇華させることを推奨する。さらなる高みへ挑戦してほしい。
