動態 SQL、應用代碼拼接 SQL 時,單引號 (字符串界定符) 的轉義是最高頻坑點。本文系統梳理 T-SQL 與常見應用語言 (VB/VBA/ASP 等) 的引號處理規則。
'Hello'。'O''Brien' → O'Brien。SET QUOTED_IDENTIFIER ON),不用於字符串。SELECT "ColumnName" FROM "TableName"; -- 列名/表名含空格/關鍵字時使用[] 也是標識符界定符 (T-SQL 專用),推薦用 QUOTENAME() 動態生成。DECLARE @Name NVARCHAR(50) = N'O''Brien'; -- 變量內單引號雙寫
DECLARE @Sql NVARCHAR(MAX) = N'SELECT * FROM Users WHERE Name = ''' + @Name + N''';';
-- 生成: SELECT * FROM Users WHERE Name = 'O''Brien';
| 數據類型 | SQL 字面量格式 | VB 拼接範例 |
|---|---|---|
| 字符串 | '值' | "INSERT INTO T(C) VALUES('" & Var & "')" |
| 數字 | 值 (無引號) | "INSERT INTO T(C) VALUES(" & Var & ")" |
| 日期 | 'YYYYMMDD' 或 'YYYY-MM-DD' (ISO 8601 最安全) | "INSERT INTO T(C) VALUES('" & Format(Var, "yyyyMMdd") & "')" |
| 布爾 | 1/0 或 'True'/'False' (視列類型) | "INSERT INTO T(C) VALUES(" & IIf(Var, 1, 0) & ")" |
INSERT INTO T(C) VALUES('固定值')'' (兩個單引號):INSERT INTO T(C) VALUES('')& Var &:INSERT INTO T(C) VALUES('' & Var & '')"INSERT INTO T(C) VALUES('" & Var & "')"-- ADO.NET (C#)
cmd.CommandText = "INSERT INTO T(C) VALUES(@Val)";
cmd.Parameters.AddWithValue("@Val", var); -- 自動處理類型、引號、注入
-- T-SQL sp_executesql
DECLARE @Sql NVARCHAR(MAX) = N'INSERT INTO T(C) VALUES(@Val)';
EXEC sp_executesql @Sql, N'@Val NVARCHAR(50)', @Val = @Var;
鐵律:應用代碼**永遠使用參數化命令**,動態 SQL 僅用於 DDL/結構變更/極複雜邏輯無法參數化時。
| 錯誤代碼 | 問題 | 修正 |
|---|---|---|
"SELECT * FROM T WHERE Name = '" & Name & "'" | Name 含單引號 → SQL 語法錯誤/注入 | 參數化;或 T-SQL 內部 REPLACE(@Name, '''', '''''') |
"SELECT * FROM T WHERE Date = " & DateVar | 日期無引號 → 語法錯誤/格式歧義 | "... WHERE Date = '" & Format(DateVar, "yyyyMMdd") & "'" |
INSERT INTO T VALUES('" & Str & "') | 列順序隱式依賴,ALTER TABLE 後報錯 | 顯式列名:INSERT INTO T(Col) VALUES(...) |
單引號雙寫是 T-SQL 字符串字面量的唯一轉義規則;應用層拼接請**直接改用參數化**,別造輪子、別信「過濾單引號就安全」的謊言。