プログラマメモ2 - programmer no memo2

jdbc IN句 2009/06/28

Javaです。JDBCです。PreparedStatementです。ふと、whereで使うIN句で、?に配列(リスト)を指定できないのかしらと思ったわけです。
どういうことかといいますと、

SELECT * FROM 品番 WHERE 品番 IN('A001')

って感じのSQLで、さらに、
SELECT * FROM 品番 WHERE 品番 IN('A001', 'A003', 'A011', 'A087')

って感じになるときに、PreparedStatementで、
SELECT * FROM 品番 WHERE 品番 IN(?, ?, ?, ?)

って指定するのではなく、ずばり、
SELECT * FROM 品番 WHERE 品番 IN(?)

はてな一個でできないかということです。

なんかできそうだよなーと思いつつもできないかもなぁという思いありつつ調べたのですが、結論は、おそらく《できない》、です。

似たように考えるひとびとは結構いるらしい、検索すると、でてきます。
Java以外の言語のAPI、ライブラリ−だとあるかもしれませんが...

その都度、SQLを組み立てればよいですが、組立てる場合、まあ、そのSQLとして問題がないように気を使う必要がでてきますね。

例えば、はてなを二個連結しするとできるとか、配列(リスト)を展開してくれるとかってはどうでしょうかねー
SELECT * FROM 品番 WHERE 品番 IN(??)





H2を使って試したコードです。
150000連結させてみました。

package a;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class Test_SelectIn {

public static void main(String[] args) {
a();
}

static void a() {

try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:~/test",
"sa", "");

// 'a001', 'a001'
String sql = "select * from 品番 where 品番 IN(@R@)";
List<String> list = new ArrayList<String>();
list.add("a001");
for (int i = 0; i < 150000; i++) {
list.add("a" + i);
}
StringBuilder sb = new StringBuilder();
for (String s : list) {
sb.append("?,");
}

if (!(sb.length() - 1 < 0) && sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length() - 1);
}
sql = sql.replace("@R@", sb);
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < list.size(); i++) {

}
int pos = 1;
for (String s : list) {
ps.setString(pos++, s);
}
System.out.println(ps.toString());
ResultSet resultSet = ps.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.toString());
}

conn.close();

} catch (Exception e) {
e.printStackTrace();
}

}
}

: