我正在努力让我们系统的java bean能够在向下运行数据库时使用SQL IN子句,但遇到了一个令人困惑的问题。
我使用以下通用模式为PreparedStatement构建SQL查询:
select [column names]
from [table name]
where [a column name] IN (?, ? , ?, ..., ?)
...表示任意数量的?取决于用户决定构建到IN子句中的值的数量。我运行一个循环来将它们放入查询字符串中。
从这里开始,我使用PreparedStatement的setString(idx,String)方法,遍历值列表并从索引1 - 值中运行。
PreparedStatement通过executeQuery()方法运行查询,返回的ResultSet似乎不正确。
在使用4个值的特定实例中,当我将PreparedStatement中的查询带到SQL并替换每个?使用''中的确切值,我得到3个结果(因为其中一个值故意不在DB中)。
另一方面,ResultSet在其集合中只有1行,并且该行始终对应于第一行? IN子句中的参数。
我甚至尝试用([列名] =?OR [列名] =?...或列名] =?)伪造IN子句,但这里也出现同样的问题。
有什么想法在这里发生了什么?顺便提一下,连接到Oracle数据库。
日志:
2010-02-10 11:16:28,505 DEBUG basic.BasicCursor - Preparing statement SELECT MERCHANT_ID, M_NAME, M_AUTHEN, M_ADMIN_AUTHEN, M_CONTACT_ADDR, M_PAYMENT_ADDR, M_HAS_MPROXY, M_DISABLED, M_FREETEXT, TXN_ID, M_TAX_NAME, M_TAX_RATE, MERCHANT_PARENT_ID, MERCHANT_ROOT_ID, RESERVED_1, RESERVED_2, RESERVED_3, RESERVED_4, EMAIL, LOGICAL_TYPE, CHANNEL_MASK FROM MERCHANT0 WHERE MERCHANT_ID IN (?, ?, ?, ?) ORDER BY MERCHANT_ID
2010-02-10 11:16:28,505 DEBUG basic.BasicCursor - Adding string to slot 1: 6172222222
2010-02-10 11:16:28,505 DEBUG basic.BasicCursor - Adding string to slot 2: 6177740603
2010-02-10 11:16:28,505 DEBUG basic.BasicCursor - Adding string to slot 3: 6177740602
2010-02-10 11:16:28,505 DEBUG basic.BasicCursor - Adding string to slot 4: 6172441111
2010-02-10 11:16:28,512 DEBUG basic.BasicCursor - scanCursor() calling... checking for next row. Current row is : 0
2010-02-10 11:16:28,512 DEBUG basic.BasicCursor - scanCursor() called, hit
2010-02-10 11:16:28,512 DEBUG basic.BasicCursor - scanCursor() got object 6172222222
2010-02-10 11:16:28,512 DEBUG basic.BasicCursor - scanCursor() calling... checking for next row. Current row is : 1
2010-02-10 11:16:28,512 DEBUG basic.BasicCursor - scanCursor() called, not hit
2010-02-10 11:16:28,505 DEBUG basic.BasicCursor - The size of variables list = 4
编辑:发现PreparedStatement的问题。我会把它留给那些好奇的人来解决它。它在上面的日志语句中可见。不幸的是,现在我的问题已经变成了一些烦人的专有代码,它们限制了从现在预期的ResultSet到显示只有1条记录的行。 叹息
答案 0 :(得分:3)
setString()
,并且您没有使用相同的值再一次next()
。System.out.println()
并检查(并可能发布)以下内容:
toString()
PreparedStatement
每次拨打setString()
toString()
来电的参数和PreparedStatement
的{{1}}
setString()
的返回值答案 1 :(得分:0)
那么,你使用过这个构造吗?
private static final String SQL = "SELECT * FROM MERCHANT0 WHERE MERCHANT_ID IN (%s)";
public List<Merchant> list(List<Long> ids) {
StringBuilder placeHolders = new StringBuilder();
for (int i = 0; i < ids.size(); i++) {
placeHolders.append("?");
if (i + 1 < ids.size()) {
placeHolders.append(",");
}
}
String sql = String.format(SQL, placeHolders.toString());
// ...
try {
// ...
preparedStatement = connection.prepareStatement(SQL);
for (int i = 0; i < ids.size(); i++) {
preparedStatement.setLong(i + 1, ids.get(i));
}
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
Long id = resultSet.getLong("MERCHANT_ID");
System.out.println(id); // Should print all of the `ids`.
}
// ...
除了Oracle在IN
子句中限制了大约1000个值之外,这应该可行。