【问题标题】:pass unknown number of parameters to IN clause using JDBC and Postgres使用 JDBC 和 Postgres 将未知数量的参数传递给 IN 子句
【发布时间】:2019-10-03 10:19:59
【问题描述】:

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

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 我需要使用其中任何一个来提高性能

【问题讨论】:

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


    【解决方案1】:

    你可以创建一个复合类型,比如

    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 的作用相同,但它可以与右侧的数组一起使用。

    【讨论】:

    • 这是最糟糕的,因为 postgres 不使用任何可用的索引
    • 你没有说你有索引。请在问题中添加索引定义。
    【解决方案2】:

    我可以使用 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,这仍然有效

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 1970-01-01
      • 2018-01-23
      • 2011-05-06
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多