10

我正在使用 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')

我在这里想念什么?

4

4 回答 4

10

使用 = 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 文档有更多详细信息。这个片段值得注意:

SOME 是 ANY 的同义词。IN 等价于 = ANY。

于 2018-09-21T06:10:35.643 回答
5

当您的数据库字段类型为 时array,您可以使用PreparedStatement.setArray()向查询发送一个数组。但是,在你的情况下,它不是一个真正的数组,而是一个没有参数的变量,你不能这样做。IE

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")三次。

如果您的参数数量不是恒定的,则动态构造查询,但是,您会降低效率。

于 2013-05-21T03:23:11.980 回答
5

PostgreSQL 有几个数组功能可以处理这种情况。

首先是 unnest 函数,从 8.4 开始可用。有点笨拙,但有效。

select * from foo where id in (SELECT * FROM unnest(?));

接下来是数组交集运算符。

select * from foo where ARRAY[id] && ?;

将您的列值转换为具有单个元素的数组,然后检查与您设置为参数的数组的交集。

据我所知,这些在功能上是等效的,但我还没有检查哪个可能更高效。

于 2015-09-23T19:40:14.073 回答
2

I'd consider this a PgJDBC issue. It should really be writing an array constructor or an array literal with an explicit cast, eg:

select * from foo where id in (ARRAY['a','b','c'])

or

select * from foo where id in ('{"a","b","c"}'::text[])

As a workaround you should be able to write:

"select * from foo where id in ( (?)::text[] )"

.. though I haven't tested to verify that.

Please consider writing this up as a unit test for PgJDBC and submit it to the PgJDBC project via github as a bug report. Look at how the existing unit tests work and just add another. It's all pretty simple JUnit.

于 2013-05-21T03:31:19.677 回答