こんにちは!Access VBAでの開発、日々お疲れ様です。
マクロの記録から一歩踏み出し、自分の手でコードを書いてシステムをコントロールする面白さを感じ始めている頃ではないでしょうか。
さて、VBAを使ってデータベースを操作していると、避けて通れないのが「SQL(エスキューエル)」の組み立てです。画面のテキストボックスに入力された値を使ってデータを検索したり追加したりする……業務アプリでは毎日のように書く処理ですよね。
ここで、多くの開発者が最初に、そして何度も直面する「魔物」がいます。
それが、シングルクォーテーション( `’` )によるSQL構文エラーです。
今回は、この厄介なエスケープ処理を完全に自動化し、あなたのコードを「絶対にエラーで止まらない頑健なシステム」に生まれ変わらせる汎用関数を授けましょう。ここをクリアすれば、Access VBAの基本はバッチリですよ!
—
1. なぜSQLの「引用符」でエラーが起きるのか?
まずは敵を知ることから始めましょう。
例えば、画面の検索窓(テキストボックス `txtSearch`)にユーザーが以下のように入力したとします。
> O’Reilly (プログラミング書籍で有名なオライリーです)
これをVBAでSQL文に組み込もうとして、次のようなコードを書いたとします。
‘ 危険なコードの例
Dim strSQL As String
strSQL = “SELECT FROM T_Books WHERE BookName = ‘” & Me.txtSearch.Value & “‘;”
このとき、パソコン(Accessのエンジン)が実際に受け取る文字列はどうなるでしょうか?
SELECT FROM T_Books WHERE BookName = ‘O’Reilly’;
……お気づきでしょうか?
`O` の後ろにあるシングルクォーテーションで、「文字列がここで終わり」とSQLに誤解されてしまうのです。その結果、残りの `Reilly’;` が予期せぬ構文とみなされ、無情な「実行時エラー(構文エラー)」が爆誕します。
撲滅すべき悪夢のパターン
- 人名や社名に `O’Brien` や `D’souza` が含まれているとき
- 備考欄に `「これ、ダメでした。」` のような全角・半角の引用符や、文章中のアポストロフィが混ざるとき
これらを人力で一つずつチェックするのは、バグを生む原因でしかありません。だからこそ、「自動で安全な形に変換する関数」をあらかじめ用意しておく必要があるのです。
—
2. 解決策:シングルクォーテーションを無害化する極意
SQLの世界では、文字列リテラルの中にあるシングルクォーテーションは、「2つ重ねる(`”`)」ことで「これはただの文字ですよ(エスケープ)」とエンジンに伝えるルールになっています。
つまり、先ほどの `O’Reilly` なら、SQL文の中で `O”Reilly` と表現されていればエラーになりません。
この変換(置換)を、VBAの `Replace` 関数を使って一瞬で行うユーティリティ関数を作りましょう。
—
3. 実装:コピペで使える「安全・確実」な汎用エスケープ関数
あなたのプロジェクトの「標準モジュール」(なければ新規作成してください)に、以下のコードをそのまま貼り付けてください。
Option Explicit
‘ ==============================================================================
‘ モジュール名: modDatabaseUtils
‘ 概要 : データベース操作に関する汎用ユーティリティ
‘ ==============================================================================
/
- SQLの文字列リテラル用にシングルクォーテーションをエスケープする
- @param ByVal vValue As Variant 処理対象の値(テキストボックス等の値)
- @return String SQLに埋め込んでも安全に加工された文字列
/
Public Function SafeSQLStr(ByVal vValue As Variant) As String
‘ 1. 万が一のNull(未入力)対策:Nullなら空文字を返す
If IsNull(vValue) Then
SafeSQLStr = “”
Exit Function
End If
‘ 2. 数値型などの場合も考慮し、一度文字列に変換
Dim strVal As String
strVal = CStr(vValue)
‘ 3. 【核心】シングルクォーテーション(‘)を2つ(”)に置換する
‘ これによりSQLの構文破壊を防ぐ
strVal = Replace(strVal, “‘”, “””)
‘ 4. 前後のシングルクォーテーションで囲んで返す
‘ ※SQL文を組み立てる際、値部分をこの関数だけで完結させるとミスが減ります
SafeSQLStr = “‘” & strVal & “‘”
End Function
この関数のスマートなポイント
1. Nullへの耐性: 画面の入力欄が空っぽ(Null)でもエラーになりません。自動的に空文字(`”`)として安全に処理されます。
2. 囲みまで自動化: 関数の戻り値自体に最初からシングルクォーテーション(`”`)を付与しているため、SQL文を書くときのクォーテーションの付け忘れ・付け間違いが物理的に起きなくなります。
—
4. 実践:動的SQL生成でのスマートな使い方
先ほどのエスケープ関数を使って、実際にクエリ定義(`QueryDef`)や `DoCmd.RunSQL` で動的SQLを組み立ててみましょう。
Public Sub SearchBooks()
Dim strSQL As String
Dim qry As DAO.QueryDef
‘ — 動的SQLの組み立て —
strSQL = “SELECT FROM T_Books WHERE ”
‘ テキストボックスの値を SafeSQLStr に通すだけ!
‘ ユーザーが「O’Reilly」と入力しても、関数が内部で自動処理してくれます。
strSQL = strSQL & “BookName = ” & SafeSQLStr(Me.txtSearch.Value) & ” ”
‘ さらに、もしあいまい検索(LIKE)にしたい場合もこの関数が使えます!
‘ 例: LIKE ‘%O”Reilly%’ のように前後に % を挟む場合
‘ strSQL = strSQL & “AND Memo LIKE ‘%” & Replace(Me.txtSearch.Value, “‘”, “””) & “%'”
‘ クエリ定義(QueryDef)オブジェクトを更新して実行
Set qry = CurrentDb.QueryDefs(“Q_DynamicSearch”)
qry.SQL = strSQL
qry.Close
Set qry = Nothing
‘ フォームのデータソースを更新して結果を表示
Me.RecordSource = “Q_DynamicSearch”
Me.Requery
MsgBox “検索が完了しました!”, vbInformation, “成功”
End Sub
どうでしょうか? SQL文の中に無理やり `’` と `&` を複雑に組み合わせる必要がなくなパッと見のコードが劇的に美しく、読みやすくなったのが分かるはずです。
—
5. 伝説のアーキテクトからのメッセージ
プログラミング初学者のうちは、「動けばいいや」と画面の入力値をそのままSQLに直結させがちです。しかし、実際の業務システムでは、ユーザーは開発者が想像もしないような文字を入力します(絵文字や全角スペース、そして今回扱ったシングルクォーテーションなど)。
今回紹介した `SafeSQLStr` のような「入力値を安全にサニタイズ(無害化)する部品」を一つ持っておくだけで、将来発生する謎のバグや、ユーザーからの「システムが急に止まった!」という悲鳴を未然に防ぐことができます。
地味ですが、こうした細部へのこだわりこそが、プロとアマを分ける境界線です。
ぜひあなたのAccessアプリにもこの関数を組み込んで、ワンランク上の安定感を手に入れてくださいね。応援しています!
