動態組合 SQL 時,若使用者輸入包含特殊字元(如 '、|、"、&),直接串接會破壞語法結構:
-- 使用者輸入 UID=1"test, PWD=A|&900
SQL = "SELECT * FROM SecurityLevel WHERE UID=""" & UserID & """"
-- 產生:SELECT * FROM SecurityLevel WHERE UID="1"test" AND PWD="A|&900"
-- 雙引號提前結束、管線符被解析為運算子,語法錯誤
最佳實務:使用參數化查詢(PreparedStatement、Command.Parameters),完全避免字串串接,同時防禦 SQL Injection。本文提供的函數僅適用於舊版無參數化支援的環境(如 ASP/VB6)。
Function ReplaceStr(TextIn, SearchStr, Replacement, CompMode)
Dim WorkText, Pointer
If IsNull(TextIn) Then ReplaceStr = Null : Exit Function
WorkText = TextIn
Pointer = InStr(1, WorkText, SearchStr, CompMode)
Do While Pointer > 0
WorkText = Left(WorkText, Pointer - 1) & Replacement & Mid(WorkText, Pointer + Len(SearchStr))
Pointer = InStr(Pointer + Len(Replacement), WorkText, SearchStr, CompMode)
Loop
ReplaceStr = WorkText
End Function
-- 標準 SQL:雙引號轉義為兩個雙引號
Function SQLFixup(TextIn)
SQLFixup = ReplaceStr(TextIn, """", """""", 0)
End Function
-- Jet/Access:額外處理管線符 (Chr(124))
Function JetSQLFixup(TextIn)
Dim Temp
Temp = ReplaceStr(TextIn, """", """""", 0)
JetSQLFixup = ReplaceStr(Temp, "|", Chr(124), 0)
End Function
-- 首字元特殊處理 (如 LIKE 模式)
Function FindFirstFixup(TextIn)
Dim Temp
Temp = ReplaceStr(TextIn, """", Chr(34) & Chr(39), 0) ' 雙引號+單引號
FindFirstFixup = ReplaceStr(Temp, "|", Chr(124), 0)
End Function
SQL = "SELECT * FROM SecurityLevel WHERE UID=""" & SQLFixup(UserID) & """ "
SQL = SQL & " AND PWD=""" & SQLFixup(PassWord) & """ "
SqlCommand.Parameters.AddWithValue("@uid", userID)PreparedStatement.setString(1, userID)PDO::prepare() + bindParam()cursor.execute("... WHERE uid=%s", (userID,))參數化查詢同時解決特殊字元、SQL 注入、執行計畫重用三大問題,請務必作為預設開發模式。