问题 org.postgresql.util.PSQLException:错误:语法错误在“$ 1”或附近


我得到这个PSQLException:

org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"
  Position: 37

当我运行以下代码时:

ps = connection.prepareStatement("SELECT current_timestamp + INTERVAL ?;");
ps.setString(1, "30 minutes");
System.out.println(ps);
rs = ps.executeQuery();

但是,println函数在控制台中显示:

SELECT current_timestamp + INTERVAL '30 minutes'

谁知道什么是错的?控制台中的查询在pgAdmin中运行正常,所以我知道它不是语法错误。


1281
2017-10-10 20:32


起源

没有区别,分号是完全有效的 - Kevin Orriss
该查询适用于我,这是实际的代码还是你有任何变量代替“30分钟” - singhakash
这是实际的代码......你在运行postgres吗? - Kevin Orriss
将字符串设置为间隔有一个错误,我确信它... setString 适用于其他字符串和 setInt 也工作...... - Kevin Orriss
好像是 postgresql bug - herry


答案:


虽然语法 INTERVAL '30 minutes' 当您直接在控制台中编写SQL时,它是有效的,它实际上被认为是一个 区间文字 并且不会在单词后面的字符串中工作 INTERVAL 不是文字字符串。

PostgreSQL中的预处理语句是在服务器端使用实现的 PREPARE 每一个 ? 被视为服务器上的实际变量。这也是它抱怨的原因 $1 虽然你从未写过 $ 在你的陈述中。

因此,字面语法不适用于预准备语句。

不要让字符串表示(结果 println准备好的声明让你感到困惑 - 这不是服务器看到的。服务器在那里看到一个变量。

因此,您需要使用带有字符串的语法(可以是变量或文字)并将其转换为间隔。例如 ?::INTERVAL 要么 CAST(? AS INTERVAL)

因此,这是  一个bug。


17
2017-10-10 21:34



非常感谢! ps = connection.prepareStatement("SELECT current_timestamp + ?::INTERVAL;");  这工作正如预期的那样,遗憾的是,我买的JSP书中没有记录这个:) - Kevin Orriss
嗯,这是一本JSP书,而不是PostgreSQL,我想。每个DBMS都有自己的怪癖,有些与它决定实现JDBC契约的具体方式有关。 - RealSkeptic
非常好的一点......当一些事情没有发挥作用我的期望时,总是快速指出手指哈哈 - Kevin Orriss


我相信这是一个Postgres bug,所以我想到了一个肮脏的黑客来解决这个问题......

ps = connection.prepareStatement("SELECT current_timestamp + INTERVAL ?;");
ps.setString(1, "30 minutes");
ps = connection.prepareStatement(ps.toString());
rs = ps.executeQuery();

我想知道这是否会得到解决?


-1
2017-10-10 21:02