2010-05-18 88 views
26

查詢碼和查詢:無法在JDBC PreparedStatement中使用LIKE查詢?

ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2"); 
ps.setString(1,"SUBSTR(DSN,27,16)"); 
ps.setInt(2,defaultWasGroup); 
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%"); 
rs = ps.executeQuery(); 
while (rs.next()) { bla blah blah blah ... 

返回一個空ResultSet

通過基本的調試,我發現它的第三綁定即即

DSN like '?' 

我已經嘗試了各種變化,這是最明智的似乎的問題可以用:

DSN like concat('%',?,'%') 

但這不起作用,因爲我在連接字符串的任一側上缺少',所以我嘗試:

DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2 

但我似乎無法找到一種方法讓他們在作品中。

我錯過了什麼?

+0

將Java代碼寫入JSP文件而不是寫入真正的Java類(您應**已經完成它),並且遇到問題特定的Java代碼不會使其成爲JSP問題。在真正的Java類中這樣做時,您將面臨完全相同的問題。所以我刪除了'[jsp]'標籤,因爲這是無關緊要的。 – BalusC 2010-05-18 12:52:36

+1

真的,它不是JSP特定的,但是根據我讀過的大多數書籍,在servlet中使用這樣的代碼沒有什麼錯誤,特別是當它是一個超過40行代碼的超級簡單報告頁面時,應用程序體系結構是有點矯枉過正:)但我很感謝你的觀點! – SeerUK 2010-05-18 13:12:02

回答

52

首先,PreparedStatement佔位符(那些?東西)僅適用於列值,不適用於表名稱,列名,SQL函數/子句等等。改用String#format()代替。其次,你應該不是引用像'?'的佔位符,它只會malformed最終查詢。 PreparedStatement制定者已經爲你做了引用(和轉義)工作。

這裏是固定的SQL:

private static final String SQL = "select instance_id, %s from eam_measurement" 
    + " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where" 
    + " resource_group_id = ?) and DSN like ? order by 2"); 

這裏是如何使用它:

String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s. 
preparedStatement = connection.prepareStatement(sql); 
preparedStatement.setInt(1, defaultWasGroup); 
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%"); 

參見

2

省略'圍繞?。沒有'?是參數的佔位符。有了它,它就是一個SQL字符串(即與Java中的"?"相同)。

然後,您必須連接Java端的字符串;您不能將SQL函數作爲參數傳遞給查詢;只有基本的值(如字符串,整數等),因爲JDBC驅動程序會將參數轉換爲數據庫期望的SQL類型,並且在此步驟中無法執行SQL函數。

+0

沒有「'圍繞?我也得到一個空的resultSet。毫不奇怪,我猜測那麼sql會讀取:和DSN類似於%Module = P_STAG_JDBC01:poolSize%,oracle不喜歡並回復:在index :: 1處缺少IN或OUT參數(錯誤代碼= 17041)因此,我需要當我通過ps.setString設置它時,添加''到綁定? – SeerUK 2010-05-18 12:37:47

+0

例如 ps.setString(3,''Module = jvmRuntimeModule:freeMemory'「); 但也給出了一個空的結果集,如同 ps.setString(3,「\'Module = jvmRuntimeModule:freeMemory \'」); 雖然java文檔說,它不應該有必要轉義'內部's – SeerUK 2010-05-18 12:39:42

+0

@ SeerUK:錯誤信息來自參數1,而不是參數3! – 2010-05-18 14:31:25

10

您的陳述有兩個問題。你必須瞭解綁定變量是如何工作的。查詢是未通過用您的參數代替字符?進行處理。而是使用佔位符編譯語句,然後在執行過程中將參數的實際值賦予數據庫。

換句話說,你解析以下查詢:

SELECT instance_id, :p1 
    FROM eam_measurement 
WHERE resource_id IN (SELECT RESOURCE_ID 
         FROM eam_res_grp_res_map 
         WHERE resource_group_id = :p2) 
    AND DSN LIKE '?' 
ORDER BY 2 

我敢肯定最後一個參數會被忽略,因爲它是一個分隔符的字符串。即使它沒有被忽略,因爲Oracle不會綁定字符串中的參數(我很驚訝它沒有引發任何錯誤,您是否捕獲異常?),因此在字符周圍設置字符是沒有意義的。

現在,如果您將DNS LIKE '?'替換爲DSN LIKE ?,並綁定"%Module=jvmRuntimeModule:freeMemory%",這將有意義並應返回正確的行。

你仍然有你的第一個參數的問題,它不會做你所期望的,也就是將要執行的查詢將等同於以下查詢:

SELECT instance_id, 'SUBSTR(DSN,27,16)' 
    FROM ... 

這是不是在所有同

SELECT instance_id, SUBSTR(DSN,27,16) 
    FROM ... 

我建議解析(= prepareStatement)下面的查詢,如果你希望在SUBSTR是動態的:

SELECT instance_id, SUBSTR(DSN,?,?) 
    FROM eam_measurement 
WHERE resource_id IN (SELECT RESOURCE_ID 
         FROM eam_res_grp_res_map 
         WHERE resource_group_id = ?) 
    AND DSN LIKE ? 
ORDER BY 2 
0

你可以試試:

String beforeAndAfter = "%" + yourVariable + "%"; 
11

如果你想在事先準備好的聲明中使用等,還希望喜歡用%字符;

寫事先準備好的聲明爲常「......怎麼樣?......」,雖然分配的參數值,以問號使用

ps.setString(1, "%" + "your string value" + "%");

這將工作:)

0

這應該工作:

"\'" + "?" + "\'" 
0
PreparedStatement ps = con.prepareStatement(
    "select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')"); 

這裏var是存儲要查找的值的變量...

+1

請給出更多的解釋和格式化您的代碼(您可以使用「倒勾」或縮進4個空格)。 [如何回答](http://stackoverflow.com/help/how-to-answer) – AgataB 2016-09-10 11:09:28