【问题标题】:Using Postgres's prepared statements from JDBC fails with "there is no parameter $1"从 JDBC 使用 Postgres 的准备好的语句失败,“没有参数 $1”
【发布时间】:2014-03-10 18:40:25
【问题描述】:

我正在尝试使用 Postgres 的官方 JDBC 驱动程序 9.3-1100 从 Scala 应用程序中使用 Postgres 9.1 的 prepared statements 功能。

如果我这样做,一切正常,我会得到“foo”:

conn.prepareStatement("PREPARE prep(text) AS SELECT $1").executeUpdate();
val cmd = conn.prepareStatement("EXECUTE prep('foo')");

但是,如果我尝试对其进行参数化:

conn.prepareStatement("PREPARE prep(text) AS SELECT $1").executeUpdate();
val cmd = conn.prepareStatement("EXECUTE prep(?)");
cmd.setString(1, "foo");

然后我在执行命令时得到这个错误:

org.postgresql.util.PSQLException: ERROR: there is no parameter $1
  Position: 14
  org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161)
  org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890)
  org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
  org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:560)
  org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
  org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:410)
  com.jolbox.bonecp.PreparedStatementHandle.execute(PreparedStatementHandle.java:140)

我已经尝试了几种不同的方法,但我找不到任何方法来成功地参数化这个查询。

我使用 Npgsql 驱动程序在 .net 应用程序中做了类似的事情,并且它可以工作,所以我不明白为什么 JDBC 驱动程序不允许我这样做。这只是 JDBC 驱动程序的限制吗?有什么解决办法吗?

【问题讨论】:

  • 所以你创建了一个prepared statement的prepared statement。嗯……
  • 这个准备好的语句的目的是什么?你能解释一下吗?对我来说,将字符串分配给参数是没有意义的,然后执行 SELECT string 并将该字符串作为结果集从数据库中检索。
  • 查看我问题顶部的链接。准备好的语句允许您一次准备一条语句,然后执行多次,从而节省服务器资源。然后服务器只需要解析和计划一次查询。这是一个准备好的语句的简单示例,只是为了演示我遇到的错误。
  • 我不知道它是否相关,但 JDBC 文档说您可以让 JDBC 准备语句函数实际使用服务器端准备 (jdbc.postgresql.org/documentation/91/server-prepare.html),这可能会给您带来您的效果重来。

标签: java postgresql jdbc


【解决方案1】:

当您使用 JDBC 准备语句时,您需要准备实际的语句。您当前正在尝试准备和执行 PostgreSQL 特定的 PREPAREEXECUTE 命令(这可能是驱动程序内部使用的)。

您需要这样做:

val cmd = conn.prepareStatement("SELECT ?");
cmd.setString(1, "foo");

虽然我不确定这是否可行,因为 PostgreSQL 无法在这里决定参数类型。

【讨论】:

  • 感谢回复,但是PREPARE和EXECUTE并不是驱动内部使用的。我正在尝试使用 Postgres 的准备好的语句功能(请参阅问题顶部的链接)。要使用这个特性,你必须先发送 PREPARE 然后 EXECUTE 到 Postgres。我知道这有点令人困惑,因为 JDBC 有一个名为“prepareStatement”的函数,但这实际上只是一个巧合,这与 Postgres 的预处理语句无关。
  • @fickerra,PostgreSQL JDBC PreparedStatement 实现已经为您完成了所有这些。
  • 具体来说(使用与PREPARE等效的协议):github.com/pgjdbc/pgjdbc/blob/master/org/postgresql/core/v3/…
  • 你是对的,它可以,但我从 .net 移植了一个手动编写自己准备好的语句的应用程序,我想以同样的方式实现该应用程序。不过,听起来 JDBC 不允许这样做,而是希望您使用它的自动准备语句系统。
  • @fickerra 考虑更改为使用 JDBC 准备好的语句作为移植工作的一部分。我真的不建议尝试绕过它。
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 1970-01-01
  • 2014-01-29
  • 2014-10-28
  • 2017-03-08
相关资源
最近更新 更多