我们正在将一些服务从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
。
2条答案
按热度按时间44u64gxh1#
这似乎有点晚,但对于可能遇到这个问题的人来说。我过去遇到过这个问题,我需要将日期(Java Date)转换为字符串,然后再转换回Date,无论我使用什么格式,转换回来时都不起作用。直到我使用日历。
字符串
在做了我必须做的转换为字符串日期后,我将其转换为整数并将其传递给日历,如上所述,你得到了训练。P.S.我希望我能引用我找到这个的来源。如果有人这样做,请在这里分享链接,我会确保引用。
zengzsys2#
正如Andreas在他的第二条评论中指出的那样,问题在于PostgreSQL的JDBC实现比其他实现更“精致”,并且希望显式地知道哪个类型是参数,即使传递的值是
null
。其他实现(如Oracle或MySQL)的情况并非如此,当值为null
时,它们都乐于将Varchar
作为默认类型。我们别无选择,只能将所有查询改为使用
COALESCE
。Here's an old thread解释问题,如果有人感兴趣,和a more recent discussion。