如何在JDBC预准备语句中转义文字问号('?')

Mik*_*din 12 java sql jdbc prepared-statement

我想创建一个JDBC PreparedStatement,如:

SELECT URL,LOCATE ( '?', URL ) pos FROM Links WHERE pageId=? ORDER BY pos ASC
Run Code Online (Sandbox Code Playgroud)

第一个?是文字而第二个?是参数.我可以使用CHAR(63)代替,'?'但我认为额外的函数调用会减慢SQL执行速度.有没有办法逃脱第一次?

编辑:

以下代码测试dkatzel的断言,即?字符串中的字符不被视为标记:

public class Test {
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection("jdbc:h2:mem:test");
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("CREATE TABLE Links(URL VARCHAR(255) PRIMARY KEY,pageId BIGINT)");
        stmt.executeUpdate("INSERT INTO Links(URL,pageId) VALUES('http://foo.bar?baz',1)");
        stmt.executeUpdate("INSERT INTO Links(URL,pageId) VALUES('http://foo.bar/baz',1)");
        stmt.close();
        PreparedStatement ps = conn
            .prepareStatement("SELECT URL,LOCATE ( '?', URL ) pos FROM Links WHERE pageId=? ORDER BY pos ASC");
         ps.setLong(1, 1);
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            System.out.println(rs.getString(1) + ":" + rs.getInt(2));
        }
        rs.close();
        ps.close();
        conn.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

http://foo.bar/baz:0
http://foo.bar?baz:15
Run Code Online (Sandbox Code Playgroud)

似乎dkatzel是正确的.我搜索了JDBC规范,并且找不到任何提及? 参数标记如果在引号内会被忽略,但是我找到的PreparedStatement解析器的几个实现(MySql,c-JDBC,H2)似乎都排除了单个文本引用作为参数标记.

bob*_*sie 17

根据您使用的JDBC驱动程序,您可以通过添加另一个问号来逃避,例如,如果您正在使用PostgreSQL

https://jdbc.postgresql.org/documentation/head/statement.html

在JDBC中,问号(?)是PreparedStatement的位置参数的占位符.但是,有许多PostgreSQL运算符包含问号.要使SQL语句中的此类问号不被解释为位置参数,请使用两个问号(??)作为转义序列.您也可以在Statement中使用此转义序列,但这不是必需的.特别是在Statement中,single(?)可以用作运算符.


Ell*_*sch 7

如果它不能与您的JDBC驱动程序一起使用,您可以将其绑定为String ?,

ps.setString(1, "?");
Run Code Online (Sandbox Code Playgroud)


Mar*_*eel 5

The meaning of the ? is specified in the SQL specification, and the JDBC specification defers to the SQL specification for this.

A driver doesn't (and shouldn't) interpret a question mark in a literal as a parameter placeholder, as a question mark within a string literal is simply a character within the string literal. For more information look at chapter 5 of SQL:2011 Foundation (ISO-9075-2:2011).

所以逃避是没有必要的(也不可能)。

  • Postgres 使用问号作为 jsonb 类型的运算符。请参阅:http://www.postgresql.org/docs/9.4/static/functions-json.html (8认同)
  • @hasen 特别是在最新的 PostgreSQL 驱动程序中,您需要将 `??` 用于 hstore ? 操作员。 (5认同)