我正在使用Java 1.7和JDBC 4以及Postgres。我试图使用带有数组的PreparedStatement来填充SQL in子句。但是,生成的SQL似乎有“{”和“}”。这是代码:
PreparedStatement ptmt =
connection.prepareStatement("select * from foo where id in (?)");
String[] values = new String[3];
values[0] = "a";
values[1] = "b";
values[2] = "c";
ptmt.setArray(1, connection.createArrayOf("text", values));
生成的SQL如下所示:
select * from foo where id in ('{"a","b","c"}')
其中,无法正常工作。这应该是它的样子:
select * from foo where id in ("a","b","c")
或
select * from foo where id in ('a','b','c')
我在这里缺少什么?
答案 0 :(得分:4)
当您的数据库字段的类型为array
时,您可以使用PreparedStatement.setArray()
将数组发送到查询。但是,在你的情况下,它不是一个真正的数组,而是一个变量no参数,你不能这样做。即。
PreparedStatement ptmt = connection.prepareStatement("select * from foo where id in (?)");
只能使用一个参数。如果要传递3个参数,则必须执行
PreparedStatement ptmt = connection.prepareStatement("select * from foo where id in (?, ?, ?)");
做ptmt.setString(n, "String")
三次。
如果你的参数不是常数,那么动态构造查询,但是你失去了效率。
答案 1 :(得分:3)
PostgreSQL有几个array capabilities可以处理这种情况。
首先是自8.4以来可用的不需要的功能。有点笨拙,但有效。
select * from foo where id in (SELECT * FROM unnest(?));
接下来是数组交集运算符。
select * from foo where ARRAY[id] && ?;
将列值转换为具有单个元素的数组,然后检查与您设置为参数的数组的交集。
据我所知,这些在功能上是等价的,但我没有检查哪些可能更高效。
答案 2 :(得分:1)
我认为这是PgJDBC问题。它应该是使用显式强制转换编写数组构造函数或数组文字,例如:
select * from foo where id in (ARRAY['a','b','c'])
或
select * from foo where id in ('{"a","b","c"}'::text[])
作为一种解决方法,您应该能够写下:
"select * from foo where id in ( (?)::text[] )"
..虽然我没有测试过验证。
请考虑将此作为PgJDBC的单元测试,并通过github将其作为错误报告提交给PgJDBC项目。看看现有的单元测试是如何工作的,只需添加另一个。这都是非常简单的JUnit。
答案 3 :(得分:0)
使用= ANY子查询表达式。
PreparedStatement ptmt = connection.prepareStatement("select * from foo where id = ANY(?)");
String[] values = new String[]{"a","b","c"};
ptmt.setArray(1, connection.createArrayOf("text", values));
如果您需要在查询中强制使用类型,可以执行以下操作。
select * from foo where id = ANY(?::text[])
PostgreSQL documentation有更多详细信息。此代码段值得注意:
SOME是ANY的同义词。 IN等于= ANY。