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プロジェクトの標準規約にこれを組み込むことを強く推奨する。
