Excel VBAエンジニアのためのSQL入門:SELECTとWHEREによるデータ抽出の極意
Excel VBAを操るエンジニアにとって、AccessデータベースやSQL Server、あるいはSQLiteといった外部データベースとの連携は、業務効率化の最終到達点とも言えます。VBAだけで複雑なループ処理を記述する時代は終わり、現在は「必要なデータをSQLで抽出し、結果をExcelに流し込む」という設計が主流です。本記事では、SQLの基本中の基本である「データの取得」に焦点を当て、SELECT文とWHERE句を使いこなすための技術的詳細を解説します。
SQLにおけるデータ取得の基本構造
SQL(Structured Query Language)は、データベースから特定の情報を「宣言的」に取得するための言語です。VBAが「どうやって(How)」処理を行うかを記述する手続き型言語であるのに対し、SQLは「何を(What)」取得したいかを記述する宣言型言語です。
データの取得にはSELECT文を用います。最も基本的な構文は以下の通りです。
SELECT カラム名 FROM テーブル名;
ここで重要なのは、データベースの世界ではExcelのシート全体を「テーブル」と見なし、列を「カラム(フィールド)」、行を「レコード」と呼ぶ点です。VBAでRangeオブジェクトを操作する際、行と列をインデックスで指定していましたが、SQLでは「カラム名」を指定して値を取り出します。
SELECT文によるカラムの選択
全てのカラムを取得したい場合は「*(アスタリスク)」を使用しますが、実務においては推奨されません。必要なカラムのみを明示的に指定することで、ネットワークトラフィックの削減や、メモリの節約、そしてコードの可読性向上につながります。
例えば、顧客データベースから「名前」と「電話番号」だけを取得したい場合、以下のように記述します。
SELECT 顧客名, 電話番号 FROM T_顧客マスタ;
VBAでADODB.Recordsetを使用してデータを取得する際、SELECTで指定した順序でデータが格納されます。このため、SELECT文での指定順序を意識することは、VBA側のコード(rs.Fields(0).Valueなど)の安定性に直結します。
WHERE句による条件指定の技術
データベースに格納された全件を取得するケースは稀です。多くの場合、特定の条件に合致するレコードだけを抽出する必要があります。ここで登場するのがWHERE句です。WHERE句はFROM句の直後に配置し、レコードを絞り込むための論理条件を記述します。
WHERE句で使用できる主な演算子は以下の通りです。
・比較演算子:=, <>, <, <=, >, >=
・論理演算子:AND, OR, NOT
・パターンマッチング:LIKE
・範囲指定:BETWEEN
・値のリスト:IN
・欠損値の判定:IS NULL
例えば、「売上金額が100万円以上、かつ地域が東京」という条件でデータを抽出する場合、SQLは以下のようになります。
SELECT 売上ID, 金額, 地域 FROM T_売上 WHERE 金額 >= 1000000 AND 地域 = ‘東京’;
ここで注意が必要なのは、文字列リテラルを記述する際のシングルクォーテーション(’)です。VBAの文字列連結と混同しやすいため、SQL文全体をダブルクォーテーションで囲み、内部の文字列をシングルクォーテーションで囲むというルールを徹底してください。
LIKE演算子によるあいまい検索
実務において、完全一致だけでなく「~を含む」といったあいまい検索は頻繁に発生します。LIKE演算子とワイルドカード(%:0文字以上の任意の文字列)を組み合わせます。
例えば、「名前」に「田中」が含まれるレコードを検索する場合:
SELECT * FROM T_顧客 WHERE 名前 LIKE ‘%田中%’;
この「%」は、VBAの「*」とは異なることに注意してください。Accessのクエリ(DAO)では「*」を使用しますが、標準的なSQL(ADO/SQL Server/SQLite等)では「%」を使用します。この違いでエラーに悩まされるエンジニアは非常に多いため、接続先のデータベースエンジンが何であるかを常に意識してください。
VBAとSQLの連携サンプルコード
以下に、ADO(ActiveX Data Objects)を使用してデータベースから条件付きでデータを取得し、Excelシートへ展開する標準的なコード例を示します。
Sub GetDataFromDatabase()
Dim conn As Object
Dim rs As Object
Dim strSQL As String
Dim connStr As String
' 接続文字列(環境に合わせて変更)
connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\DB\Sales.accdb;"
' SQL文の構築
strSQL = "SELECT 顧客名, 売上金額 FROM T_売上 " & _
"WHERE 地域 = '大阪' AND 売上金額 > 50000 " & _
"ORDER BY 売上金額 DESC;"
Set conn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
conn.Open connStr
rs.Open strSQL, conn
' シートへの書き出し
If Not rs.EOF Then
Sheet1.Range("A2").CopyFromRecordset rs
End If
' 後処理
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
End Sub
実務におけるプロフェッショナルなアドバイス
1. SQL文の可読性
SQL文をVBAのコード内で1行に詰め込むのは避けましょう。上記サンプルコードのように、アンダースコア(_)を用いた連結を行い、改行を入れて整形してください。また、予約語(SELECT, FROM, WHERE等)はすべて大文字で記述するのが業界の慣習です。
2. インデックスの意識
WHERE句で指定するカラムには、データベース側でインデックスを貼ることを検討してください。数万件以上のレコードを扱う場合、インデックスがないと検索速度が劇的に低下します。VBA側でいくらコードを高速化しても、データベース側のクエリが遅ければ意味がありません。
3. SQLインジェクションへの対策
VBAの入力フォームから受け取った値を直接SQL文に連結するのは非常に危険です。悪意のあるユーザーがSQL文を改ざんする「SQLインジェクション」攻撃を受ける可能性があります。入力値は必ずサニタイズ(エスケープ処理)を行うか、パラメータクエリを利用して安全にデータを渡す習慣を身につけましょう。
4. NULL値の取り扱い
データベースにおいて、値が「空」であることを示すNULLは、通常の比較演算子(=)では拾えません。「IS NULL」または「IS NOT NULL」を正しく使い分けることが、データの欠損を防ぐ鍵となります。
まとめ
SQLによるデータ取得は、現代のExcel業務自動化における中核技術です。SELECT文で必要なカラムを絞り込み、WHERE句で的確に条件を指定する。この基本動作をマスターするだけで、VBAのコード量は激減し、処理速度とメンテナンス性は飛躍的に向上します。
最初は複雑に感じるかもしれませんが、データベースと対話するこの言語は、一度習得すれば一生モノのスキルとなります。まずは手元の小さなデータベースから、WHERE句を使った条件抽出を試してみてください。エラーが出た際も、それはデータベースがあなたに「SQLの構造が正しくない」と教えてくれているサインです。焦らずログを確認し、一歩ずつプロフェッショナルなデータ操作術を磨き上げていきましょう。
