【问题标题】:org.postgresql.util.PSQLException: ERROR: syntax error at or near "$1"org.postgresql.util.PSQLException:错误:“$1”处或附近的语法错误
【发布时间】:2016-01-08 14:34:56
【问题描述】:

我收到了这个 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 中运行良好,所以我知道这不是语法错误。

【问题讨论】:

  • 没什么区别,分号完全有效
  • 查询对我有用,这是实际代码还是您有任何变量代替“30 分钟”
  • 这是实际代码...你在运行 postgres 吗?
  • 有一个将字符串设置为间隔的错误,我敢肯定...setString 适用于其他字符串,setInt 也适用...
  • 好像是postgresql bug

标签: java postgresql jdbc


【解决方案1】:

虽然 INTERVAL '30 minutes' 语法在你直接在控制台中编写 SQL 时是有效的,但它实际上被认为是一个 间隔文字,并且在单词 @987654323 后面的字符串中不起作用@ 不是文字字符串。

PostgreSQL 中的预处理语句是在服务器端使用PREPARE 实现的,每个? 都被视为服务器上的一个实际变量。这也是它抱怨$1 的原因,尽管您从未在声明中写过$

因此,文字语法不适用于准备好的语句。

不要让准备好的语句的字符串表示(println 的结果)让您感到困惑——这不是服务器所看到的。服务器在那里看到一个变量。

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

因此,这不是错误。

【讨论】:

  • 非常感谢! ps = connection.prepareStatement("SELECT current_timestamp + ?::INTERVAL;"); 这按预期工作,可惜我买的 JSP 书中没有记录:)
  • 嗯,我想这是一本 JSP 书,而不是 PostgreSQL 书。每个 DBMS 都有自己的怪癖,其中一些与它决定实现 JDBC 契约的具体方式有关。
  • 确实很好......当某些事情没有按照我的预期工作时,总是快速指指点点哈哈
【解决方案2】:

我相信这是一个 Postgres 错误,所以我想了一个肮脏的 hack 来解决这个问题......

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

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

【讨论】:

  • 为什么这个答案被否决了?这种方法有什么缺点吗?
  • 它应该被否决,这是一个快速/肮脏的修复,直到出现正确的铸造答案。不应该创建一个准备好的语句,然后使用第一个准备好的语句的 toString 创建另一个。它有效,但不是正确的做法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 2017-07-02
  • 1970-01-01
  • 2021-11-30
  • 2019-11-23
  • 2016-11-22
  • 2017-02-20
相关资源
最近更新 更多