2010-08-10 207 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