Postgres SQL in子句和setArray()

Doo*_*Dah 7 java postgresql jdbc

我使用的是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));
Run Code Online (Sandbox Code Playgroud)

生成的SQL如下所示:

select * from foo where id in ('{"a","b","c"}')
Run Code Online (Sandbox Code Playgroud)

哪个,不行.它应该是这样的:

select * from foo where id in ("a","b","c")
Run Code Online (Sandbox Code Playgroud)

要么

select * from foo where id in ('a','b','c')
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么?

小智 7

使用 = 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));
Run Code Online (Sandbox Code Playgroud)

如果您需要在查询中强制执行类型,您可以执行类似的操作。

select * from foo where id = ANY(?::text[])
Run Code Online (Sandbox Code Playgroud)

PostgreSQL文档有更多的细节。这个片段值得注意:

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


Pra*_*ati 5

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

PreparedStatement ptmt =  connection.prepareStatement("select * from foo where id in (?)");
Run Code Online (Sandbox Code Playgroud)

只能取一个参数。如果要传递3个参数,则必须执行

PreparedStatement ptmt =  connection.prepareStatement("select * from foo where id in (?, ?, ?)");
Run Code Online (Sandbox Code Playgroud)

并做ptmt.setString(n, "String")三次。

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


小智 5

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

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

select * from foo where id in (SELECT * FROM unnest(?));
Run Code Online (Sandbox Code Playgroud)

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

select * from foo where ARRAY[id] && ?;
Run Code Online (Sandbox Code Playgroud)

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

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