【入門編】SQLの「UNION ALL」を動的に生成する:複数のテーブルからデータを統合する汎用関数 – Access VBA解析バイブル

スポンサーリンク

こんにちは。Accessの迷宮に足を踏み入れ、データ活用の新たな扉を開こうとしているあなたへ。

これまで「クエリ作成画面」でマウスをカチカチと動かしていた作業から一歩進んで、「コードでクエリを操る」という領域に足を踏み入れましょう。今回は、複数のテーブルを合体させる魔法の呪文「UNION ALL」を、VBAを使って自由自在に生成する方法を伝授します。

これができるようになると、Accessのポテンシャルは劇的に変わりますよ。

—

なぜ「動的SQL」なのか?

通常、クエリ定義(QueryDef)は固定されたものを作りがちです。しかし、業務では「今月はA支店とB支店のデータが欲しい」「来月は全支店のデータが必要」といった変動がつきもの。

毎回手動でクエリを書き換えるのは、ミスのもとであり、何より美しくありません。「必要な時に、必要なパーツを繋ぎ合わせてSQLを作り出す」。これこそが、脱・初心者エンジニアへの登竜門です。

—

UNION ALLの基本をおさらい

`UNION ALL`は、複数の同じ構造を持つテーブルを「縦に積み重ねる」命令です。

SELECT ID, 名前 FROM テーブルA
UNION ALL
SELECT ID, 名前 FROM テーブルB

これをVBAで扱う際、最大の難関は「テーブルの数だけSQLを繋ぐ文字列操作」です。

—

魔法の汎用関数:GenerateUnionSQL

それでは、テーブル名のリストを渡すと、自動的に`UNION ALL`で結合されたSQL文字列を生成する関数を書いてみましょう。

‘ ———————————————————
‘ 機能: テーブル名の配列からUNION ALL SQLを生成する
‘ 引数: tableNames() – 結合したいテーブル名の配列
‘ 戻り値: 完成したSQL文字列
‘ ———————————————————
Public Function GenerateUnionSQL(tableNames() As String) As String
Dim i As Long
Dim sqlBuilder As String

‘ SQLの組み立て開始
For i = LBound(tableNames) To UBound(tableNames)
‘ 各テーブルからデータを抽出するSQLを定義
‘ ※ここでは全カラム取得していますが、必要に応じて調整してください
sqlBuilder = sqlBuilder & “SELECT FROM ” & tableNames(i)

‘ 最後のテーブル以外には UNION ALL を追加する
If i < UBound(tableNames) Then sqlBuilder = sqlBuilder & " UNION ALL " & vbCrLf End If Next i GenerateUnionSQL = sqlBuilder End Function

コードの解説:ここがポイント!

1. ループ処理(For文): `LBound`から`UBound`を使うことで、配列の要素数に関係なく柔軟に対応できます。
2. 文字列の連結: `&`演算子を使ってSQLを繋いでいます。`vbCrLf`は改行コードです。これを入れると、後でSQLを確認する際に可読性が格段に上がります。
3. 分岐処理(If文): `UNION ALL`を「テーブルとテーブルの間」だけに挿入するテクニックです。末尾に余計な`UNION ALL`が残るのを防ぐ、プロの気遣いです。

—

実践:QueryDefで動的にクエリを保存する

生成したSQLを実際にAccessの「クエリ」として保存してみましょう。

Public Sub SaveUnionQuery()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim tables(1 To 2) As String

Set db = CurrentDb

‘ 結合したいテーブル名を指定
tables(1) = “売上2023”
tables(2) = “売上2024”

‘ 先ほどの関数でSQLを作成
Dim mySQL As String
mySQL = GenerateUnionSQL(tables)

‘ クエリが存在すれば削除し、新しく作成する(クリーンな状態を保つ)
On Error Resume Next
db.QueryDefs.Delete “qry_Union_Result”
On Error GoTo 0

Set qdf = db.CreateQueryDef(“qry_Union_Result”, mySQL)

MsgBox “クエリ ‘qry_Union_Result’ を作成しました!”, vbInformation
End Sub

—

初学者が陥りやすい罠と対策

1. 「フィールドの数が合わない」エラー
`UNION ALL`は、結合するテーブル同士で「列の数」と「データ型」が一致している必要があります。もしエラーが出たら、まずは各テーブルのフィールド構成を確認してください。
2. SQLインジェクションへの配慮
今回はテーブル名を固定で渡していますが、もし画面入力から受け取る場合は、必ず「許可されたテーブル名か」をチェックしてください。悪意のある文字列を埋め込まれないための防衛策です。
3. パフォーマンスの意識
`UNION`ではなく`UNION ALL`を使う理由は、`UNION`だと「重複データの排除(ソート処理)」が発生し、動作が重くなるからです。実務では原則`ALL`を使いましょう。

—

先輩からのアドバイス

「コードを書くこと」は目的ではありません。「業務の苦痛を、コードで自動化して消し去ること」が私たちのゴールです。

最初は難しく感じるかもしれませんが、この「文字列を組み立ててSQLを作る」という考え方は、Accessにおける最強の武器の一つです。まずはこのコードをコピーして、ご自身の環境で動かしてみてください。画面に「クエリ」がパッと現れた時の快感は、何物にも代えがたいはずです。

何か詰まったら、いつでも戻ってきてくださいね。応援しています!

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