【実務・中級編】ADOのCommandオブジェクトを活用したパラメータクエリによるSQLインジェクション対策 – Access VBA解析バイブル

スポンサーリンク

Access VBAの暗黒面を払拭せよ:ADO Commandオブジェクトによる「堅牢な」SQL実行術

業務システム開発の現場で、未だに「文字列連結」でSQLを組み立てているコードを見かける。
`”SELECT FROM Users WHERE Name = ‘” & Me.txtName & “‘”`
もし君がこれを書いているなら、今すぐキーボードから手を離してほしい。それは単なる怠慢ではない。「システムを自ら破壊しに行く行為」と同義だからだ。

今日は、Access VBAにおける「DAOとADOの使い分け」、そして最も重要な「ADO CommandオブジェクトによるSQLインジェクション対策」について、伝説的アーキテクトの視点から説く。

—

1. DAOとADO:その「非情な」境界線

Access開発において、多くのエンジニアがDAOとADOを気分で使い分けている。だが、アーキテクチャの観点では明確な役割分担がある。

  • DAO (Data Access Objects): Accessのネイティブエンジン。ローカルテーブルの操作や、Access内のフォーム連携において圧倒的な速度を誇る。Accessファイルを完結させるならDAOで十分だ。
  • ADO (ActiveX Data Objects): SQL Serverや外部DBとの接続、高度なトランザクション制御、そして今回解説する「パラメータクエリ」の実装に不可欠な汎用エンジンだ。

結論: 外部DBへの接続や、セキュリティが求められる動的SQLの生成には、迷わずADOを採用せよ。

—

2. なぜ文字列連結は「悪」なのか?

文字列連結でSQLを作る最大の罪は、「型情報の欠落」と「SQLインジェクションの脆弱性」だ。

例えば、ユーザー入力値に `’ OR ‘1’=’1` と入れられたらどうなるか?君のシステムは無防備に全データを晒すことになる。また、日付型や数値型のフォーマット変換でバグを埋め込むリスクも極めて高い。

これを解決するのが、CommandオブジェクトとParametersコレクションだ。SQLの骨格とデータを分離することで、実行エンジンは「入力値が何であるか」を厳密に解釈し、悪意あるコードを「ただの文字列」として処理する。

—

3. 実装の極意:プロフェッショナルなADO接続パターン

現場で即戦力となる、保守性の高いADO実行コードをここに提供する。これをベースに、自社のフレームワークを構築せよ。

‘ 参照設定: Microsoft ActiveX Data Objects x.x Library を有効にすること
Public Sub ExecuteSecureUpdate(ByVal targetID As Long, ByVal userName As String)
Dim conn As ADODB.Connection
Dim cmd As ADODB.Command
Dim strSQL As String

‘ 1. コネクションの確立
Set conn = CurrentProject.Connection ‘ カレントDB接続の場合

‘ 2. パラメータをプレースホルダ(?)にしたSQLを定義
strSQL = “UPDATE Users SET UserName = ? WHERE UserID = ?”

Set cmd = New ADODB.Command
With cmd
Set .ActiveConnection = conn
.CommandText = strSQL
.CommandType = adCmdText

‘ 3. パラメータの型を厳密に指定(ここが防御の要)
‘ CreateParameter(名前, 型, 方向, サイズ, 値)
.Parameters.Append .CreateParameter(“pName”, adVarWChar, adParamInput, 50, userName)
.Parameters.Append .CreateParameter(“pID”, adInteger, adParamInput, , targetID)

‘ 4. トランザクション処理の開始(データ整合性の担保)
conn.BeginTrans
On Error GoTo RollbackHandler

.Execute , , adExecuteNoRecords

conn.CommitTrans
End With

Set cmd = Nothing
Set conn = Nothing
Exit Sub

RollbackHandler:
conn.RollbackTrans
MsgBox “エラー発生: ” & Err.Description, vbCritical
End Sub

—

4. アーキテクトからの「最後のアドバイス」

このコードのどこが優れているか、理解できただろうか?

1. 分離の原則: SQL構文とデータ値が明確に分かれている。これにより、SQLエンジンは解析済みパス(Execution Plan)を再利用できるため、パフォーマンスも向上する。
2. トランザクション管理: `BeginTrans`と`Rollback`をセットで記述することで、予期せぬエラーでデータが中途半端に更新される「腐敗したデータ」を防いでいる。
3. 型安全: `adVarWChar`や`adInteger`といった明確な型指定により、型の不一致による実行時エラーを未然に排除している。

最後に一言。
「コードが動くこと」と「コードが守られていること」は別次元の話だ。君たちが書くコードは、君たちが現場を去った後も生き続ける。次世代のエンジニアに技術的負債を残すな。

パラメータクエリを使いこなすことは、エンジニアとしての「品格」である。今日から、君のAccessプロジェクトの標準規約にこれを組み込むことを強く推奨する。

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