Java中的参数化Oracle SQL查询?
我一直在试图找出为什么下面的代码不会产生在我的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中的更改。
任何帮助将不胜感激,谢谢!
我认为问题是你的数据类型是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
谢谢!我真的希望我可以改变数据类型,但它是一个受保护的数据库,我只能查询它。 – echoblaze 2010-08-10 18:55:31
需要检查的两件事:1)如果您不使用表格,其中一列的名称与表格相同,是否仍会发生? 2)你确定你正在对结果集进行迭代 - 如果你对查询进行硬编码而不是使用参数,你会得到结果吗? – 2010-08-10 16:43:23
对于它的价值,你的第一个例子对我来说看起来很好。乔恩可能会在“学校”表中的“学校”专栏中提到 - 这个*不应该成为问题,但是你的代码不应该失败...... – 2010-08-10 16:53:57
出于好奇,试试第一个示例(带'?'的示例),但将参数设置为带有尾部空格的“Waterloo”。 MySQL应该忽略尾随空格,但是在这种情况下,司机可能会做些简单的事情。 – 2010-08-10 17:03:42