動態 SQL 中單引號處理不當是典型 Bug 來源:'O'Brien' 會導致語法錯誤,更嚴重的是為 SQL Injection 打開大門。本文對比兩種處理技法,結論明確:參數化查詢才是正解。
Function ProcessStr(str As String) As String
Dim pos As Integer
pos = InStr(str, "'")
While pos > 0
str = Mid(str, 1, pos) & "'" & Mid(str, pos + 1)
pos = InStr(pos + 2, str, "'")
Wend
ProcessStr = str
End Function
原理: 掃描字串,每發現一個單引號,在其前插入另一個單引號(SQL Server 轉義規則)。
缺點:
Dim cmd As New ADODB.Command
cmd.ActiveConnection = conn
cmd.CommandText = "SELECT * FROM Users WHERE Name = ?"
cmd.CommandType = adCmdText
cmd.Parameters.Append cmd.CreateParameter("Name", adVarChar, adParamInput, 50, userInput)
Set rs = cmd.Execute
原理: 將使用者輸入視為資料而非程式碼,由提供者負責正確編碼傳輸。
優點:
cmd.CommandText = "usp_GetUserByName"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("@Name", adVarChar, adParamInput, 50, userInput)
// ADO.NET - 永遠使用參數化
using (var cmd = new SqlCommand("SELECT * FROM Users WHERE Name = @Name", conn))
{
cmd.Parameters.AddWithValue("@Name", userInput);
using (var reader = cmd.ExecuteReader()) { ... }
}
| 維度 | 轉義字元法 | 參數化查詢 | 預存程序+參數化 |
|---|---|---|---|
| 安全性 | 低(僅單引號) | 高(完整防禦) | 最高(權限隔離) |
| 效能 | 低(字串操作+重編譯) | 高(計畫重用) | 最高(預編譯+計畫持久化) |
| 維護性 | 差(散落各處) | 良(集中參數化) | 優(封裝邏輯) |
| 適用場景 | 極簡臨時腳本/舊代碼修補 | 所有新開發動態 SQL | 核心業務/高頻/高安全需求 |
單引號處理不是字串處理問題,而是程式碼與資料邊界問題。轉義字元法是權宜之計,參數化查詢才是工程正解。新專案零容忍字串串接 SQL,舊專案以參數化重構為優先技術債清償項目。