0

我正在尝试使用以下内容执行准备好的语句:

dbaBean.setPrepStmt(dbaBean.getConn().prepareStatement(
    "SELECT id, author, title, url, article_text, date_created " +
            "FROM articles WHERE " +
            "(EXTRACT(YEAR FROM date_created) = ? OR ? is null) " +
            "AND (EXTRACT(MONTH FROM date_created) = ? OR ? is null) " +
            "AND (EXTRACT(DAY FROM date_created) = ? OR ? is null) AND " +
            "(url = ? OR ? is null) " +
            "ORDER BY date_created DESC;"));

dbaBean.getPrepStmt().setString(1, year);
dbaBean.getPrepStmt().setString(2, year);
dbaBean.getPrepStmt().setString(3, month);
dbaBean.getPrepStmt().setString(4, month);
dbaBean.getPrepStmt().setString(5, day);
dbaBean.getPrepStmt().setString(6, day);
dbaBean.getPrepStmt().setString(7, URL);
dbaBean.getPrepStmt().setString(8, URL);

System.out.println(dbaBean.getPrepStmt().toString());

dbaBean 是一个提供连接和准备好的语句的对象。它根本不做任何操作。

我已经非常成功地将上述代码用于其他方法,并且完全没有遇到任何问题。现在这个函数似乎在末尾剥离分号,例如这是 System.out 行的输出:

SELECT id, author, title, url, article_text, date_created FROM articles WHERE (EXTRACT(YEAR FROM date_created) = NULL OR NULL is null) AND (EXTRACT(MONTH FROM date_created) = NULL OR NULL is null) AND (EXTRACT(DAY FROM date_created) = NULL OR NULL is null) AND (url = 'someurl' OR 'someurl' is null) ORDER BY date_created desc

注意缺少的分号。

我尝试添加第二个分号,它也被“吃掉”了。

其他更改被很好地传播(例如要选择的另一个字段)。

如果重要的话,这是 postgresql。

编辑:我在乎,因为我在运行此查询时出错,我认为删除分号是潜在的罪魁祸首。下面的答案似乎表明情况并非如此,我需要在别处寻找它。

4

2 回答 2

4

我花了几分钟浏览 Postgresql JDBC 驱动程序源代码,看来发生的事情如下:

  • 创建准备好的语句时,驱动程序会进行部分解析以将 SQL 拆分为语句,查找占位符并(我认为)删除任何注释。

  • 解析的结果存储在PreparedStatement对象中的片段序列。

  • 如果您调用toString()该语句,该方法将重构 SQL,插入占位符的值,并在每个语句之间添加分号……如果有多个语句。

所以,消失的分号是一个特性,而不是一个错误。JDBC 规范中的任何内容都没有要求该toString()方法应以其原始形式为您提供查询……或任何形式。此外,在为 JDBC 编写 SQL 时,通常使用(至少对于 Postgresql)来省略尾随分号。

于 2012-06-06T13:18:00.243 回答
3

preparedStatement(String sql)方法接受输入字符串并创建一个CallableStatement用于调用数据库存储过程的对象。

在CallableStatement对象的初始化过程中,sql字符串被jdbc驱动转换成系统原生的SQL语法。

由于分号是 Postgresql 的分隔符,您可以假设它已被 jdbc 驱动程序删除,并且如果使用其他 jdbc 驱动程序实现可能会有所不同。所以最好的选择是从你的 SQL 字符串中删除它。

于 2012-06-06T12:43:45.580 回答