【入門編】DAOとADOのハイブリッド設計:ローカル一時テーブルと外部DBの連携アーキテクチャ – Access VBA解析バイブル

スポンサーリンク

こんにちは!Access VBAの世界へようこそ。
ここまで踏み込んで勉強しようとしているあなたなら、きっと「もっとファイルを軽くしたい」「外部のSQL Serverとスムーズに連携させたい」といった、実務でのリアルな壁にぶつかっていることでしょう。

大丈夫、安心してください。今回は、Access VBAの真骨頂である「DAO」と、外部データベース接続の王様である「ADO」のそれぞれの強みを組み合わせた、「ハイブリッド設計」の極意を伝授します。

ここをクリアすれば、あなたの作るAccessアプリは見違えるほど高速化し、プロ顔負けの堅牢なシステムに生まれ変わりますよ。それでは、一緒に紐解いていきましょう!

—

1. なぜ「DAO」と「ADO」を使い分ける必要があるのか?

Access VBAでデータベースを操作する際、必ず耳にするのが DAO (Data Access Objects) と ADO (ActiveX Data Objects) です。

初学者のうちは「どっちを使えばいいの?」と迷いがちですが、プロの現場での答えはシンプルです。

  • DAOの得意分野:

Accessの「ローカル環境(今自分が開いているファイルの中)」にあるテーブル操作。とにかく爆速です。

  • ADOの得意分野:

SQL ServerやOracleなど、外部の「サーバー型データベース」との通信。接続の安定性と、高度なSQL(トランザクション含む)の実行に長けています。

💡 現場の黄金律:「適材適所のハイブリッド」

大量のデータ加工や一時的な計算を、いきなり外部のSQL Server上でやろうとすると、ネットワークの往復(オーバーヘッド)が発生して処理が重くなります。

そこで、今回のテーマであるハイブリッド設計の出番です。
1. 【DAOで高速処理】 外部からデータを軽く持ってくるか、Access内のローカル一時テーブル上で、ガリガリと高速にデータを加工・集計する。
2. 【ADOで書き戻し】 最終的に綺麗に整った結果だけを、ADOを使ってSQL Serverへ一気にドカンと書き戻す。

このデータフローをマスターすれば、処理スピードが何倍にも跳ね上がります!

—

2. アーキテクチャの全体像(データフロー)

まずは、今回目指す仕組みを頭の中にイメージしましょう。

[ 外部SQL Server ]
▲
│ (1) ADOでデータを取得
▼
[ Access ローカル一時テーブル ]
│
│ (2) DAOで高速なレコード走査・加工
▼
[ 加工済みローカル一時テーブル ]
│
│ (3) ADOでSQL Serverへトランザクション書込
▼
[ 外部SQL Server (最終結果) ]

「一時テーブルなんて使わなくてもクエリで一発では?」と思うかもしれませんが、複雑な業務ロジックや条件分岐が絡む場合、VBAとDAOを組み合わせた一時テーブルでの逐次処理の方が、後々のメンテナンス性で圧倒的に有利な場面が多いのです。

—

3. 実装コード:ハイブリッド設計の全貌

それでは、開発現場でそのままコピペして使える実践的なコードを公開します。
今回は、「ローカルの一時テーブルでデータを整え、SQL Serverのマスターテーブルへトランザクション付きで一括書き込みを行う」シナリオを想定しています。

Option Compare Database
Option Explicit

‘ ==============================================================================
‘ 【メイン処理】DAOとADOを融合させたハイブリッド・データローダー
‘ ==============================================================================
Public Sub ExecuteHybridProcess()

‘ エラーハンドリングの準備(実務では必須です!)
On Error GoTo ErrorHandler

Dim db As DAO.Database
Dim rsLocal As DAO.Recordset

Dim conn As Object // ADO Connection
Dim cmd As Object // ADO Command
Dim strConn As String
Dim lngCount As Long

Set db = CurrentDb
lngCount = 0

‘ ————————————————————————–
‘ STEP 1: DAOによるローカル一時テーブルの高速読み込み
‘ ————————————————————————–
‘ ※あらかじめ「tmp_WorkData」というローカルテーブルがAccess内にある前提です
Set rsLocal = db.OpenRecordset(“SELECT FROM tmp_WorkData WHERE ProcessedFlag = False”, dbOpenDynaset)

If rsLocal.EOF Then
MsgBox “処理対象のデータが存在しません。”, vbInformation, “通知”
GoTo CleanUp
End If

‘ ————————————————————————–
‘ STEP 2: ADOによる外部SQL Serverへの接続確立
‘ ————————————————————————–
Set conn = CreateObject(“ADODB.Connection”)

‘ SQL Serverへの接続文字列(環境に合わせて書き換えてください)
strConn = “Provider=SQLOLEDB;Server=YOUR_SERVER_NAME;Database=YOUR_DB_NAME;Uid=YOUR_USER;Pwd=YOUR_PASSWORD;”

conn.ConnectionTimeout = 30
conn.Open strConn

‘ ————————————————————————–
Id: ‘ STEP 3: トランザクションを開始して安全に書き戻し
‘ ————————————————————————–
conn.BeginTrans

Do Until rsLocal.EOF

‘ — ここでDAOを使ったローカル側のデータ加工・参照ができる(高速!) —
Dim targetId As Long
Dim targetValue As String

targetId = rsLocal!ID
targetValue = rsLocal!ItemName & ” (Processed)”

‘ ADOコマンドを使ってSQL Serverへ書き込み
Dim sql As String
sql = “INSERT INTO Remote_MasterTable (RecordID, ItemName, CreatedAt) VALUES (?, ?, ?)”

Set cmd = CreateObject(“ADODB.Command”)
Set cmd.ActiveConnection = conn
cmd.CommandText = sql

‘ パラメータクエリでSQLインジェクション対策と型安全性を担保
cmd.Parameters.Append cmd.CreateParameter(“ID”, 3, 1, , targetId) // 3 = adInteger
cmd.Parameters.Append cmd.CreateParameter(“Name”, 200, 1, 255, targetValue) // 200 = adVarChar
cmd.Parameters.Append cmd.CreateParameter(“Date”, 135, 1, , Now) // 135 = adDateTime

cmd.Execute

‘ 処理済みフラグをローカル側(DAO)で更新
rsLocal.Edit
rsLocal!ProcessedFlag = True
rsLocal.Update

lngCount = lngCount + 1
rsLocal.MoveNext
Loop

‘ すべて成功したらコミット
conn.CommitTrans

MsgBox lngCount & ” 件のデータをSQL Serverへ正常に同期しました!”, vbInformation, “処理成功”

CleanUp:
‘ ————————————————————————–
‘ STEP 4: 確実なオブジェクトの解放(メモリリーク防止)
‘ ————————————————————————–
On Error Resume Next
If Not rsLocal Is Nothing Then rsLocal.Close: Set rsLocal = Nothing
If Not db Is Nothing Then Set db = Nothing

If Not conn Is Nothing Then
If conn.State = 1 Then conn.Close
Set conn = Nothing
End If
Exit Sub

ErrorHandler:
‘ 異常発生時はトランザクションをロールバックして変更をなかったことにする
If Not conn Is Nothing Then
If conn.State = 1 Then conn.TransactCount > 0 Then conn.RollbackTrans
End If

MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub

—

4. コードの深掘りと「陥りやすい罠」の回避策

上記のコードには、プロのエンジニアが現場で必ず組み込むべき「生き残りの知恵」が詰まっています。いくつか重要なポイントを解説します。

① オブジェクトの解放(メモリ管理)をサボらない

Access VBAにおいて、`Recordset` や `Connection` を開きっぱなしにするのは、メモリのガソリンタンクに火種を放り込むようなものです。必ず `Set … = Nothing` で綺麗にメモリから消去しましょう。
特に、ループ内で `Command` オブジェクトを生成・破棄する際は、ループのスコープとメモリの肥大化に注意が必要です。

② トランザクション(`BeginTrans` / `CommitTrans` / `RollbackTrans`)の重要性

外部DBへの書き込み途中で、ネットワークが切れたり、データに不備があったりしてエラーが起きたとき、中途半端なデータがDBに残ると大惨事になります。
ADOのトランザクションを使うことで、「すべて成功するか、すべて無かったことにするか」の安全地帯(ACID特性)を確保できます。

③ パラメータクエリ(`CreateParameter`)の徹底

SQLの文字列を `sql = “INSERT INTO … VALUES (” & targetId & “, ‘” & targetValue & “‘)” ` のように直接結合して書くのは絶対にNGです(SQLインジェクションや、シングルクォーテーションのエスケープ漏れによる構文エラーの原因になります)。
ADOのパラメータオブジェクトを使い、型を明示して安全に値を渡しましょう。

—

5. おわりに:ここをクリアすれば、もう怖くない!

お疲れ様でした!DAOとADOのハイブリッド設計、そのコンセプトと実装のイメージは掴めましたでしょうか?

  • ローカルの快適な操作には「DAO」
  • 外部サーバーとの堅牢な通信には「ADO」

この2つを適材適所で使い分けられるようになると、Accessは単なる「オフィスの便利ツール」から、「堅牢で高速な業務システムのフロントエンド」へと劇的に進化します。

最初は難しく感じるかもしれませんが、エラー処理やトランザクションの型を一度自分のテンプレートにしてしまえば、どんな巨大な案件でも怖くありません。
ここをクリアしたあなたなら、もうAccess VBAの初学者卒業です。ぜひ、実際の業務データで試してみてくださいね!応援しています!

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