標籤:拼接sql語句中的特殊字元
在實際的項目開發中,往往會根據使用者在介面的文字框中輸入的資訊,去資料庫中做模糊查詢。如果使用的是原始的JDBC和SQL,往往需要對使用者的輸入進行轉義,避免產生的sql語法錯誤,或者防止SQL注入。比如對輸入的%和_和‘,就需要進行轉義,因為這3個字元是SQL的特殊字元,如果不處理會導致sql出錯或者是查詢資料不正確。
假如有這樣1個查詢請求,模糊查詢標題中包含a%b_cc‘d的記錄,正確的sql應該是下面這樣的:
select * from t_sch_work_info t where t.title like '%a/%b/_cc''d%' ESCAPE '/';
這就需要對String content = "a%b_cc‘d";進行轉義後,再拼成SQL語句。oracle資料庫允許我們使用自己定義的字元作為逸出字元。看了下我們項目DAO層的編碼風格,使用到了2種逸出字元 \ 和 / 。定位問題的時候發現,有人拼接SQL語句出錯。自己用這2種字元,寫了2個公用方法,經過測試是正確的。
/** * * 對content的內容進行轉換後,在作為oracle查詢的條件欄位值。使用/作為oracle的逸出字元,比較合適。<br> * 既能達到效果,而且java代碼相對容易理解,建議這種使用方式<br> * "%'" + content + "'% ESCAPE '/' "這種拼接sql看起來也容易理解<br> * * @param content * @return */ public static String decodeSpecialCharsWhenLikeUseBackslash(String content) { // 單引號是oracle字串的邊界,oralce中用2個單引號代表1個單引號 String afterDecode = content.replaceAll("'", "''"); // 由於使用了/作為ESCAPE的轉義特殊字元,所以需要對該字元進行轉義 // 這裡的作用是將"a/a"轉成"a//a" afterDecode = afterDecode.replaceAll("/", "//"); // 使用逸出字元 /,對oracle特殊字元% 進行轉義,只作為普通查詢字元,不是模糊比對 afterDecode = afterDecode.replaceAll("%", "/%"); // 使用逸出字元 /,對oracle特殊字元_ 進行轉義,只作為普通查詢字元,不是模糊比對 afterDecode = afterDecode.replaceAll("_", "/_"); return afterDecode; } /** * 對content的內容進行轉換後,在作為oracle查詢的條件欄位值。使用\作為oracle的逸出字元。<br> * 這種做法也能達到目的,但不是好的做法,比較容易出錯,而且代碼很那看懂。<br> * "%'" + content + "'% ESCAPE '\' "這種拼接sql實際上是錯誤的.<br> * "%'" + content + "'% ESCAPE '\\' "這種拼接sql才是正確的<br> * * @param content * @return */ public static String decodeSpecialCharsWhenLikeUseSlash(String content) { // 單引號是oracle字串的邊界,oralce中用2個單引號代表1個單引號 String afterDecode = content.replaceAll("'", "''"); // 由於使用了\作為ESCAPE的轉義特殊字元,所以需要對該字元進行轉義 // 由於\在java和Regex中都是特殊字元,需要進行特殊處理 // 這裡的作用是將"a\a"轉成"a\\a" afterDecode = afterDecode.replaceAll("\\\\", "\\\\\\\\"); // 使用逸出字元 \,對oracle特殊字元% 進行轉義,只作為普通查詢字元,不是模糊比對 afterDecode = afterDecode.replaceAll("%", "\\\\%"); // 使用逸出字元 \,對oracle特殊字元_ 進行轉義,只作為普通查詢字元,不是模糊比對 afterDecode = afterDecode.replaceAll("_", "\\\\_"); return afterDecode; }
對比上面的代碼,很容易看出使用/,代碼更簡單,更容易理解。之所以寫這個部落格,不是推薦大家去手動拼接SQL字串,因為這種做法效率很低,而且很容易出錯。實際開發中,我們應該使用JDBC或者hibernate等架構,提供的先行編譯SQL。使用先行編譯語句不僅讓代碼可讀性更好,而且還會有效能優勢。可以參考這篇文章:
HQL或SQL使用?帶來的好處:減少SQL解析時間、降低記憶體開銷、防止SQL注入
java用字串拼接SQL語句的特殊字元轉義問題