Java中PostgreSQL查询中的可选日期参数不工作

b4lqfgs4  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(2)|浏览(165)

我们正在将一些服务从Oracle迁移到PostgreSQL,并且我们有基于JDBC的自定义数据库访问层。几乎所有的用例都可以工作,但是我们的可选参数查询(where field = :parameter or :parameter is null)不能。
Oracle中的原始查询是:

select field
from table
where (reference = ?)
  and (date >= ? or ? is null)

字符串
它工作了,我们在MySQL中测试了它,它也工作了。然而,在PostgreSQL中,我们得到了以下错误:org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $3
我们直接使用JDBC PostgreSQL库进行测试:

private static void testQuery() {
   try {
      String ref = "dummy";
      String sql = "select field From table where (reference = ?)";
      sql += " and (date >= ? or ? is null) ";
      PreparedStatement ps = getConnection().prepareStatement(sql);
      ps.setString(1, ref);
      ps.setNull(2, Types.NULL);
      ps.setNull(3, Types.NULL);
      ResultSet rs = ps.executeQuery();
      while (rs.next()) {
         System.out.print("Column 1 returned: ");
         System.out.println(rs.getString(1));
      }
      rs.close();
      ps.close();
   } catch (Exception ex) {
      ex.printStackTrace();
   }
}


我们用coalesce函数进行了测试,它工作正常,但我们的想法是让纯SQL查询可以在任何数据库中工作。
我们使用PostgreSQL 12.4,依赖关系是:

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.16</version>
</dependency>


我们可以让它工作,

ps.setNull(2, Types.NULL);
ps.setNull(3, Types.VARCHAR);


在比较一个参数和null时,似乎必须指定VARCHAR类型。这对我们没有太大帮助,因为从查询的Angular 来看,这是同一个参数,所以我们不能根据在数据库访问层中是否使用条件is null来放置两个类型。
到目前为止,每当参数为null时,我们都使用VARCHAR作为Oracle和MySQL访问的默认值,但PostgreSQL对第二个参数(日期)给出了以下错误:
org.postgresql.util.PSQLException: ERROR: operator does not exist: timestamp without time zone >= character varying
有什么想法吗?
编辑:如果我没有弄错的话,也没有误读this thread,除了在查询中指定可空参数的类型的选项(在我看来很难看)之外,没有真正的解决方案:select * from my_table where ?::timestamp

44u64gxh

44u64gxh1#

这似乎有点晚,但对于可能遇到这个问题的人来说。我过去遇到过这个问题,我需要将日期(Java Date)转换为字符串,然后再转换回Date,无论我使用什么格式,转换回来时都不起作用。直到我使用日历。

Calendar calendar = Calendar.getInstance()
calendar.set(Calendar.YEAR, 1999)
calendar.set(Calendar.DAY_OF_MONTH, 1)
calendar.set(Calendar.MONTH, 12)
java.sql.Date sqlDate = new java.sql.Date(calendar.getTime().getTime())

字符串
在做了我必须做的转换为字符串日期后,我将其转换为整数并将其传递给日历,如上所述,你得到了训练。P.S.我希望我能引用我找到这个的来源。如果有人这样做,请在这里分享链接,我会确保引用。

zengzsys

zengzsys2#

正如Andreas在他的第二条评论中指出的那样,问题在于PostgreSQL的JDBC实现比其他实现更“精致”,并且希望显式地知道哪个类型是参数,即使传递的值是null。其他实现(如Oracle或MySQL)的情况并非如此,当值为null时,它们都乐于将Varchar作为默认类型。
我们别无选择,只能将所有查询改为使用COALESCE
Here's an old thread解释问题,如果有人感兴趣,和a more recent discussion

相关问题