使用JDBC和Postgres将未知数量的参数传递给IN子句

时间:2019-10-03 10:19:59

标签: postgresql jdbc spring-jdbc postgresql-11 pg-jdbc

我的查询看起来像这样,并且运行良好:

select * 
from table t 
where (t.one,t.two,t.three) in ( (11,12,13), (21,22,23) );

现在in语句中这些三元组的数量将有所不同,因此我正在尝试对JDBC执行以下操作:

String sql = "select * from table where (one, two, three) in (select * from unnest(?::smallint[], ?::integer[], ?::integer[]))"
// conn is the java.sql.Connection
PreparedStatement ps = conn.prepareStatement(sql);
ps.setArray(1, conn.createArrayOf("smallint", new Short[]{11, 21}));
ps.setArray(2, conn.createArrayOf("integer", new Integer[]{12,22}));
ps.setArray(3, conn.createArrayOf("integer", new Integer[]{13,23}));
return ps;

那表现糟透了。那么,有没有一种方法可以使用jdbc发送三胞胎,使最终结果等同于sql查询?

我将有两个btree索引,一个在one, two上,另一个在one, three上,我需要使用任何一个btree索引才能使他表现出色

2 个答案:

答案 0 :(得分:0)

您可以创建一个复合类型,例如

CREATE TYPE triple AS (
   a smallint,
   b integer,
   c integer
);

然后您可以这样编写查询:

SELECT * 
FROM t 
WHERE (t.one, t.two, t.three) = ANY (?::triple[]);

您可以将数组作为单个字符串提供,如下所示:

{(11\,12\,13), (21\,22\,23)}

= ANYIN的功能相同,但是可以与右侧的数组一起使用。

答案 1 :(得分:0)

我可以使用NamedParameterJdbcTemplate

String sql = "select * from table " +
        "where (one, two, three) in (:valuesMap)";

List<Integer[]> valuesMap = new ArrayList<>();
valuesMap.add(new Integer[]{11,12,13});
valuesMap.add(new Integer[]{21,22,23});
SqlParameterSource params = new MapSqlParameterSource("valuesMap", valuesMap);

return jdbc.query(sql, params, resultSetExtractor);

尽管onesmallint

,该方法仍然有效