2011-07-13 46 views
1

有沒有內置方法來轉義SQL的字符串?我會使用setString,但是它發生在相同的組合SQL語句中多次使用setString,如果轉義只發生一次,而不是每次我說setString時,性能會更好(我認爲)。如果我有一個變量中的轉義字符串,我可以重新使用它。Java SQL不使用setString逃脫

在Java中沒有辦法做到這一點嗎?

當前方法,多源搜索。實際上,他們是三個完全不同的地方,包括連接,但在這個例子中,我將只顯示每個表的位置。

String q = '%' + request.getParameter("search") + '%'; 
PreparedStatement s = s("SELECT a,b,c FROM table1 where a = ? UNION select a,b,c from table2 where a = ? UNION select a,b,c FROM table3 where a = ?"); 
s.setString(1, q); 
s.setString(2, q); 
s.setString(3, q); 
ResultSet r = s.executeQuery(); 

我知道這不是什麼大不了的事,但我喜歡把事情效率,還有些情況下它是更具可讀性使用" + quote(s) + ",而不是?,然後某處在線下找到setString

+0

你想逃避什麼人物角色? – RMT

+0

這將有助於您向我們展示您的一些代碼。 – dustmachine

+0

@RMT:由'轉義的所有字符setString'我不想因爲搜索的價值注入攻擊或語法錯誤的可能性。 –

回答

4

簡短的回答:我不會理會。最好在最後一刻的時候逃避。當您嘗試儘早將字符串轉義並保留時,驗證所有字符串只能被轉義一次變得困難得多。 (兩次轉義字符串幾乎與不轉義字符一樣糟糕!)我見過很多程序嘗試儘早地轉義字符串,然後遇到麻煩,因爲它們需要更新字符串,然後程序員忘記重新創建字符串,做逃逸,或者更新字符串的轉義版本,或者他們有四個字符串,並且他們逃脫了其中的三個,等等(我正在研究一個程序員提前對字符串進行HTML轉義的bug,然後決定了他不得不截斷字符串以適應表單,並最終嘗試輸出以「& am」結尾的字符串。也就是說,他截斷了他的轉義序列,使其不再有效。)

CPU時間逃避一個字符串應該是微不足道的。除非你有大量的記錄或重複使用的大字符串,否則我懷疑節省是值得擔心的。你可能會花更多的時間來優化查詢:保存一個記錄的讀取可能會比通過字符串轉義邏輯消除1000次行程更有價值。

較長的答案:沒有內置函數。你可以很容易地寫出一個:大多數SQL的風格只需要你加倍任何單引號。您可能還需要反斜槓或一個或兩個其他特殊字符。事實上,SQL引擎之間的差異可能是不同的,這是使用PreparedStatements並讓JDBC擔心它的重要理由之一。 (就我個人而言,我認爲應該有一個JDbC函數做轉義,然後可以知道任何特定於數據庫引擎的要求,但並不是這樣的)。

無論如何,它不清楚它是如何將與PreparedStatement一起工作。必須有某種方式來告訴PreparedStatement不要轉義這個字符串,因爲它已經被轉義了。誰真的知道JDBC和數據庫引擎之間的對話表中發生了什麼事情:也許它從來沒有真正轉義它,但將它從查詢中單獨傳遞出去。我想在setString上可能會有一個額外的參數,表示「這個字符串是預先轉義的」,但是這會增加複雜性和潛在的錯誤,從而獲得很少的收益。

+1

爲什麼不再回答顯得較短,則簡短的回答:S +1以及描述這個問題, – RMT

+3

@RMT:因爲我不能獨自離開的東西,我不停地回去,並增加我的答案很簡單! – Jay

5

如果使用setString的參數(例如PreparedStatement.setString),有可能是沒有實際需要轉義 - 很可能是該數據將被從SQL本身分別通過,在不需要逃避的方式。

您是否有任何具體的跡象表明這真的是的性能瓶頸?這似乎不太可能,數據庫查詢中,昂貴的部分是在本地設置參數...

+0

這不太可能。這裏沒有瓶頸。我只是喜歡a)有效的代碼和b)有時它更具可讀性。查看我編輯的最後部分。 –

+0

@George:我不同意的可讀性,實際上 - 因爲用事先準備好的聲明你保持*碼*從*數據分開*。但我同意,命名參數更可讀的比那些位置:) –

+1

@Downvoter:護理評論? –

1

您可以使用StringEscapeUtils從Apache的百科全書:

org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL); 
3

不要使用org.apache.commons.lang.StringEscapeUtils.escapeSql(yourUnscapedSQL);

它並不像逃跑\

+1

作爲對原始問題的評論,這會更好。它並沒有真正回答這個問題。 –

+0

應該被修改以獲得所有使用StringEscapeUtils.escapeSql的建議(這種命名非常危險 - 正如Kim指出的那樣,它不能正確地轉義sql)。任何試圖在生產中依賴StringEscapeUtils的人都會失敗。 – user467257