【问题标题】:Escaping hstore contains operators in a JDBC Prepared statement转义 hstore 包含 JDBC Prepared 语句中的运算符
【发布时间】:2022-03-16 00:25:19
【问题描述】:

我正在使用带有 hstore 和 PostgreSQL JDBC 驱动程序 (9.1-901.jdbc4) 的 PostgreSQL 9.1.4。

我正在尝试在 PreparedStatement 中使用包含运算符(??&?|),但是 ? 字符被解析为变量占位符。能否转义此字符以在查询中发送正确的运算符?

一个例子:

PreparedStatement stmt = conn.prepareStatement("SELECT a, b FROM table1 WHERE c ? 'foo' AND d = ?");
stmt.setInt(1, dValue);
stmt.executeQuery();

在这种形式下,以下示例会引发异常:

org.postgresql.util.PSQLException: No value specified for parameter 2.

更新:

在 pgjdbc 驱动程序this snippet 中调查查询解析器后似乎表明无法转义? 字符。剩下的问题是:

  • JDBC 规范中是否有任何内容允许 ? 被转义并成为参数占位符以外的任何内容?
  • 对于这个问题,除了使用简单的语句并将变量手动插入到查询字符串中之外,还有什么更好的解决方法吗?

【问题讨论】:

  • 不知道任何 JDBC 但d = $1 有效吗?
  • 不,这不是有效的语法。在$1 处引发语法错误。
  • 许多 PostgreSQL 接口更喜欢编号占位符(即$1$2,...),我猜 JDBC 不是其中之一。

标签: postgresql jdbc hstore


【解决方案1】:

实际上,java SQL 解析器似乎不兼容 hstore。

但由于语法c ? 'foo' 等价于exist(c, 'foo'),因此您可以轻松解决此问题。请查看以下页面,了解 hstore 的 verbose 运算符是什么。

Postgres hstore documentation

【讨论】:

  • 谢谢,我没有看到下面的详细操作符。
  • 请注意exist(c, 'foo') 确实使用索引。检查带有和不带有的查询计划以查看差异。
【解决方案2】:

pgsql-hackers 邮件列表上有关于这个问题的讨论:http://grokbase.com/t/postgresql/pgsql-hackers/1325c6ys9n/alias-hstores-to-so-that-it-works-with-jdbc

目前我最喜欢这个也支持索引的解决方法:

CREATE FUNCTION exist_inline (hstore, text) RETURNS bool AS $$ SELECT $1 ? $2; $$ LANGUAGE sql;

【讨论】:

    【解决方案3】:

    如果您想使用 PreparedStatement 添加多个键值对,那么您可以这样做:

    PreparedStatement ps = c.prepareStatement(
                         "insert into xyz(id, data) values(?, hstore(?, ?))");
    
    ps.setLong(1, 23456L);
    ps.setArray(2, c.createArrayOf("text", new String[]{"name", "city"}));
    ps.setArray(3, c.createArrayOf("text", new String[]{"Duke", "Valley"}));
    

    这将插入:23456, 'name=>Duke, city=>Valley'

    【讨论】:

    • 这与提出的问题无关
    【解决方案4】:

    您可以使用此查询来查找支持 PostgreSQL 中的运算符的函数,如下所示。在您的示例中:

    SELECT 
      oprname, 
      oprcode || '(' || format_type(oprleft,  NULL::integer) || ', ' 
                     || format_type(oprright, NULL::integer) || ')' AS function
    FROM pg_operator 
    WHERE oprname LIKE '?%'
    AND (SELECT oid FROM pg_type WHERE typname = 'hstore') IN (oprleft, oprright);
    

    这会产生:

    |oprname|function                  |
    |-------|--------------------------|
    |?      |exist(hstore, text)       |
    |?|     |exists_any(hstore, text[])|
    |?&     |exists_all(hstore, text[])|
    

    See also a related question about using JSON operators containing ?。请注意,使用GIN index on your HSTORE column 时,函数使用可能无法从相同的索引功能中受益。

    【讨论】:

      猜你喜欢
      • 2017-10-17
      • 2014-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 2013-04-25
      相关资源
      最近更新 更多