2010-08-10 254 views
4

我一直在試圖找出爲什麼下面的代碼不會產生在我的ResultSet中的任何數據:Java中的參數化Oracle SQL查詢?

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = ? "; 
PreparedStatement prepStmt = conn.prepareStatement(sql); 
prepStmt.setString(1, "Waterloo"); 
ResultSet rs = prepStmt.executeQuery(); 

在另一方面,以下運行正常:

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = 'Waterloo' "; 
PreparedStatement prepStmt = conn.prepareStatement(sql); 
ResultSet rs = prepStmt.executeQuery(); 

數據類型學校是CHAR(9字節)。而不是setString,我也試過:

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL = ? "; 
PreparedStatement prepStmt = conn.prepareStatement(sql); 
String school = "Waterloo"; 
Reader reader = new CharArrayReader(school.toCharArray()); 
prepStmt.setCharacterStream(1, reader, 9); 
prepStmt.setString(1, "Waterloo"); 
ResultSet rs = prepStmt.executeQuery(); 

我完全停留在接下來的調查中; Eclipse調試器說,即使在setString或setCharacterStream之後,SQL查詢也不會改變。我不確定是否因爲設置參數不起作用,或者調試器無法獲取PreparedStatement中的更改。

任何幫助將不勝感激,謝謝!

+0

需要檢查的兩件事:1)如果您不使用表格,其中一列的名稱與表格相同,是否仍會發生? 2)你確定你正在對結果集進行迭代 - 如果你對查詢進行硬編碼而不是使用參數,你會得到結果嗎? – 2010-08-10 16:43:23

+0

對於它的價值,你的第一個例子對我來說看起來很好。喬恩可能會在「學校」表中的「學校」專欄中提到 - 這個*不應該成爲問題,但是你的代碼不應該失敗...... – 2010-08-10 16:53:57

+0

出於好奇,試試第一個示例(帶'?'的示例),但將參數設置爲帶有尾部空格的「Waterloo」。 MySQL應該忽略尾隨空格,但是在這種情況下,司機可能會做些簡單的事情。 – 2010-08-10 17:03:42

回答

8

我認爲問題是你的數據類型是CHAR(9),「滑鐵盧」只有8個字符。 我假設這會返回預期的結果(LIKE和%)。或者添加缺失的空間。

String sql = "SELECT STUDENT FROM SCHOOL WHERE SCHOOL LIKE ? "; 
PreparedStatement prepStmt = conn.prepareStatement(sql); 
prepStmt.setString(1, "Waterloo%"); 
ResultSet rs = prepStmt.executeQuery(); 

如果您的字符串具有靈活的長度,最好的方法是使用varchar而不是char。然後PreparedStatement將按預期工作。

解決方法是使用Oracle特定的setFixedCHAR方法(但如果可能,最好將數據類型更改爲varchar)。

以下是從Oracle的的PreparedStatement的JavaDoc:


在數據庫中CHAR數據被填充到列寬度。這會導致使用setCHAR()方法將字符數據綁定到SELECT語句的WHERE子句中的限制 - WHERE子句中的字符數據也必須填充到列寬以在SELECT語句中產生匹配。如果您不知道列寬,這尤其麻煩。

setFixedCHAR()可以解決這個問題。此方法執行非填充比較。

注:

  • 記住要投你準備語句對象以OraclePreparedStatement使用setFixedCHAR()方法。
  • 對於INSERT語句,不需要使用setFixedCHAR()。數據庫在插入數據時會自動將數據填充到列寬。

以下示例演示了setString(),setCHAR()和setFixedCHAR()方法之間的區別。

// Schema is : create table my_table (col1 char(10)); 
//    insert into my_table values ('JDBC'); 
PreparedStatement pstmt = conn.prepareStatement 
("select count() from my_table where col1 = ?"); 
ResultSet rs; 

pstmt.setString (1, "JDBC"); // Set the Bind Value 
rs = pstmt.executeQuery(); // This does not match any row 
// ... do something with rs 
CHAR ch = new CHAR("JDBC  ", null); 
((OraclePreparedStatement)pstmt).setCHAR(1, ch); // Pad it to 10 bytes 
rs = pstmt.executeQuery();  // This matches one row 
// ... do something with rs 
((OraclePreparedStatement)pstmt).setFixedCHAR(1, "JDBC"); 
rs = pstmt.executeQuery();  // This matches one row 
// ... do something with rs 
+0

謝謝!我真的希望我可以改變數據類型,但它是一個受保護的數據庫,我只能查詢它。 – echoblaze 2010-08-10 18:55:31