SQL 拼接中單引號導致語法錯誤是經典坑。本文對比 VB/ADO 環境下字符串轉義函數與 ADODB.Command 參數化查詢兩大方案的原理、代碼實現與性能差異。
Function ProcessStr(str As String) As String
Dim pos As Integer, result As String
pos = InStr(str, "'")
While pos > 0
str = Left(str, pos) & "'" & Mid(str, pos + 1) ' 在單引號前插入單引號
pos = InStr(pos + 2, str, "'")
Wend
ProcessStr = str
End Function
' 使用
sql = "SELECT * FROM users WHERE name = '" & ProcessStr(txtName.Text) & "'"
缺陷:
Dim cmd As New ADODB.Command
Dim param As ADODB.Parameter
Set cmd.ActiveConnection = cnn1
cmd.CommandText = "SELECT * FROM employee WHERE fname = ?"
cmd.CommandType = adCmdText
' 創建參數:名稱、類型、方向、大小、值
Set param = cmd.CreateParameter("p_fname", adVarChar, adParamInput, 50, txtName.Text)
cmd.Parameters.Append param
Set rst = cmd.Execute
' 結果集處理...
核心優勢:
cmd.CommandType = adCmdStoredProc + 參數 → 預編譯 + 執行計劃緩存 + 網絡傳輸最小化
' 測試數據含單引號:'Paolo''f'、'Paolo'f'
' 方案一:轉義函數 + 拼接 SQL
' 方案二:Command 參數化
' 方案三:存儲過程 + 參數化 (最高效)
結論:方案二/三在安全性、性能、可維護性上全面碾壓方案一。現代開發原則:永不拼接 SQL,永遠使用參數化查詢/ORM。
| 平台 | 參數化 API | ORM 推薦 |
|---|---|---|
| .NET (ADO.NET) | SqlCommand.Parameters.Add() | Entity Framework Core / Dapper |
| Java (JDBC) | PreparedStatement.setString() | MyBatis / JPA (Hibernate) |
| PHP (PDO) | $stmt->bindParam() | Laravel Eloquent / Doctrine |
| Python (DB-API) | cursor.execute(sql, params) | SQLAlchemy / Django ORM |
| Go (database/sql) | db.QueryContext(ctx, sql, args...) | GORM / sqlx |