【実務・中級編】【実務】大規模なテーブル分割(正規化)をVBAで自動化する移行スクリプト – Access VBA解析バイブル

スポンサーリンク

大規模テーブル分割の流儀: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という老練なプラットフォームを掌握し、業務自動化の頂点へ至るための唯一の道だ。

次のステップとして、このスクリプトを「ログ記録機能付きのライブラリ」へと昇華させることを推奨する。さらなる高みへ挑戦してほしい。

タイトルとURLをコピーしました